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::WebAXRoleEmbeddedObject:
82 return result.append("EmbeddedObject");
83 case blink::WebAXRoleFigcaption:
84 return result.append("Figcaption");
85 case blink::WebAXRoleFigure:
86 return result.append("Figure");
87 case blink::WebAXRoleFooter:
88 return result.append("Footer");
89 case blink::WebAXRoleForm:
90 return result.append("Form");
91 case blink::WebAXRoleGrid:
92 return result.append("Grid");
93 case blink::WebAXRoleGroup:
94 return result.append("Group");
95 case blink::WebAXRoleGrowArea:
96 return result.append("GrowArea");
97 case blink::WebAXRoleHeading:
98 return result.append("Heading");
99 case blink::WebAXRoleHelpTag:
100 return result.append("HelpTag");
101 case blink::WebAXRoleHorizontalRule:
102 return result.append("HorizontalRule");
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::WebAXRoleIncrementor:
112 return result.append("Incrementor");
113 case blink::WebAXRoleInlineTextBox:
114 return result.append("InlineTextBox");
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::WebAXRoleMathElement:
138 return result.append("MathElement");
139 case blink::WebAXRoleMath:
140 return result.append("Math");
141 case blink::WebAXRoleMatte:
142 return result.append("Matte");
143 case blink::WebAXRoleMenuBar:
144 return result.append("MenuBar");
145 case blink::WebAXRoleMenuButton:
146 return result.append("MenuButton");
147 case blink::WebAXRoleMenuItem:
148 return result.append("MenuItem");
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::WebAXRoleNavigation:
156 return result.append("Navigation");
157 case blink::WebAXRoleNone:
158 return result.append("None");
159 case blink::WebAXRoleNote:
160 return result.append("Note");
161 case blink::WebAXRoleOutline:
162 return result.append("Outline");
163 case blink::WebAXRoleParagraph:
164 return result.append("Paragraph");
165 case blink::WebAXRolePopUpButton:
166 return result.append("PopUpButton");
167 case blink::WebAXRolePresentational:
168 return result.append("Presentational");
169 case blink::WebAXRoleProgressIndicator:
170 return result.append("ProgressIndicator");
171 case blink::WebAXRoleRadioButton:
172 return result.append("RadioButton");
173 case blink::WebAXRoleRadioGroup:
174 return result.append("RadioGroup");
175 case blink::WebAXRoleRegion:
176 return result.append("Region");
177 case blink::WebAXRoleRootWebArea:
178 return result.append("RootWebArea");
179 case blink::WebAXRoleRowHeader:
180 return result.append("RowHeader");
181 case blink::WebAXRoleRow:
182 return result.append("Row");
183 case blink::WebAXRoleRulerMarker:
184 return result.append("RulerMarker");
185 case blink::WebAXRoleRuler:
186 return result.append("Ruler");
187 case blink::WebAXRoleSVGRoot:
188 return result.append("SVGRoot");
189 case blink::WebAXRoleScrollArea:
190 return result.append("ScrollArea");
191 case blink::WebAXRoleScrollBar:
192 return result.append("ScrollBar");
193 case blink::WebAXRoleSeamlessWebArea:
194 return result.append("SeamlessWebArea");
195 case blink::WebAXRoleSearch:
196 return result.append("Search");
197 case blink::WebAXRoleSheet:
198 return result.append("Sheet");
199 case blink::WebAXRoleSlider:
200 return result.append("Slider");
201 case blink::WebAXRoleSliderThumb:
202 return result.append("SliderThumb");
203 case blink::WebAXRoleSpinButtonPart:
204 return result.append("SpinButtonPart");
205 case blink::WebAXRoleSpinButton:
206 return result.append("SpinButton");
207 case blink::WebAXRoleSplitGroup:
208 return result.append("SplitGroup");
209 case blink::WebAXRoleSplitter:
210 return result.append("Splitter");
211 case blink::WebAXRoleStaticText:
212 return result.append("StaticText");
213 case blink::WebAXRoleStatus:
214 return result.append("Status");
215 case blink::WebAXRoleSystemWide:
216 return result.append("SystemWide");
217 case blink::WebAXRoleTabGroup:
218 return result.append("TabGroup");
219 case blink::WebAXRoleTabList:
220 return result.append("TabList");
221 case blink::WebAXRoleTabPanel:
222 return result.append("TabPanel");
223 case blink::WebAXRoleTab:
224 return result.append("Tab");
225 case blink::WebAXRoleTableHeaderContainer:
226 return result.append("TableHeaderContainer");
227 case blink::WebAXRoleTable:
228 return result.append("Table");
229 case blink::WebAXRoleTextArea:
230 return result.append("TextArea");
231 case blink::WebAXRoleTextField:
232 return result.append("TextField");
233 case blink::WebAXRoleTimer:
234 return result.append("Timer");
235 case blink::WebAXRoleToggleButton:
236 return result.append("ToggleButton");
237 case blink::WebAXRoleToolbar:
238 return result.append("Toolbar");
239 case blink::WebAXRoleTreeGrid:
240 return result.append("TreeGrid");
241 case blink::WebAXRoleTreeItem:
242 return result.append("TreeItem");
243 case blink::WebAXRoleTree:
244 return result.append("Tree");
245 case blink::WebAXRoleUnknown:
246 return result.append("Unknown");
247 case blink::WebAXRoleUserInterfaceTooltip:
248 return result.append("UserInterfaceTooltip");
249 case blink::WebAXRoleValueIndicator:
250 return result.append("ValueIndicator");
251 case blink::WebAXRoleWebArea:
252 return result.append("WebArea");
253 case blink::WebAXRoleWindow:
254 return result.append("Window");
256 return result.append("Unknown");
260 std::string GetDescription(const blink::WebAXObject& object) {
261 std::string description = object.accessibilityDescription().utf8();
262 return description.insert(0, "AXDescription: ");
265 std::string GetHelpText(const blink::WebAXObject& object) {
266 std::string help_text = object.helpText().utf8();
267 return help_text.insert(0, "AXHelp: ");
270 std::string GetStringValue(const blink::WebAXObject& object) {
272 if (object.role() == blink::WebAXRoleColorWell) {
274 object.colorValue(r, g, b);
275 value = base::StringPrintf("rgb %7.5f %7.5f %7.5f 1",
276 r / 255., g / 255., b / 255.);
278 value = object.stringValue().utf8();
280 return value.insert(0, "AXValue: ");
283 std::string GetRole(const blink::WebAXObject& object) {
284 std::string role_string = RoleToString(object.role());
286 // Special-case canvas with fallback content because Chromium wants to treat
287 // this as essentially a separate role that it can map differently depending
289 if (object.role() == blink::WebAXRoleCanvas &&
290 object.canvasHasFallbackContent()) {
291 role_string += "WithFallbackContent";
297 std::string GetTitle(const blink::WebAXObject& object) {
298 std::string title = object.title().utf8();
299 return title.insert(0, "AXTitle: ");
302 std::string GetOrientation(const blink::WebAXObject& object) {
303 if (object.isVertical())
304 return "AXOrientation: AXVerticalOrientation";
306 return "AXOrientation: AXHorizontalOrientation";
309 std::string GetValueDescription(const blink::WebAXObject& object) {
310 std::string value_description = object.valueDescription().utf8();
311 return value_description.insert(0, "AXValueDescription: ");
314 std::string GetAttributes(const blink::WebAXObject& object) {
315 // FIXME: Concatenate all attributes of the AXObject.
316 std::string attributes(GetTitle(object));
317 attributes.append("\n");
318 attributes.append(GetRole(object));
319 attributes.append("\n");
320 attributes.append(GetDescription(object));
324 blink::WebRect BoundsForCharacter(const blink::WebAXObject& object,
325 int characterIndex) {
326 DCHECK_EQ(object.role(), blink::WebAXRoleStaticText);
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);
332 end += inline_text_box.stringValue().length();
333 if (characterIndex < start || characterIndex >= end)
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: {
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);
350 return blink::WebRect(
351 inline_text_box_rect.x, inline_text_box_rect.y,
352 character_offsets[0], inline_text_box_rect.height);
354 case blink::WebAXTextDirectionRL: {
355 int right = inline_text_box_rect.x + inline_text_box_rect.width;
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);
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);
369 case blink::WebAXTextDirectionTB: {
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);
377 return blink::WebRect(inline_text_box_rect.x, inline_text_box_rect.y,
378 inline_text_box_rect.width, character_offsets[0]);
380 case blink::WebAXTextDirectionBT: {
381 int bottom = inline_text_box_rect.y + inline_text_box_rect.height;
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);
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]);
398 return blink::WebRect();
401 void GetBoundariesForOneWord(const blink::WebAXObject& object,
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);
410 end += inline_text_box.stringValue().length();
411 if (end <= character_index)
413 int localIndex = character_index - start;
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);
421 // If there are no words, use the InlineTextBox boundaries.
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];
437 // Return the last word by default.
438 word_start = start + starts[word_count - 1];
439 word_end = start + ends[word_count - 1];
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 {
449 AttributesCollector() {}
450 ~AttributesCollector() {}
452 void CollectAttributes(const blink::WebAXObject& object) {
453 attributes_.append("\n------------\n");
454 attributes_.append(GetAttributes(object));
457 std::string attributes() const { return attributes_; }
460 std::string attributes_;
462 DISALLOW_COPY_AND_ASSIGN(AttributesCollector);
467 gin::WrapperInfo WebAXObjectProxy::kWrapperInfo = {
468 gin::kEmbedderNativeGin};
470 WebAXObjectProxy::WebAXObjectProxy(const blink::WebAXObject& object,
471 WebAXObjectProxy::Factory* factory)
472 : accessibility_object_(object),
476 WebAXObjectProxy::~WebAXObjectProxy() {}
478 gin::ObjectTemplateBuilder
479 WebAXObjectProxy::GetObjectTemplateBuilder(v8::Isolate* isolate) {
480 return gin::Wrappable<WebAXObjectProxy>::GetObjectTemplateBuilder(isolate)
481 .SetProperty("role", &WebAXObjectProxy::Role)
482 .SetProperty("title", &WebAXObjectProxy::Title)
483 .SetProperty("description", &WebAXObjectProxy::Description)
484 .SetProperty("helpText", &WebAXObjectProxy::HelpText)
485 .SetProperty("stringValue", &WebAXObjectProxy::StringValue)
486 .SetProperty("x", &WebAXObjectProxy::X)
487 .SetProperty("y", &WebAXObjectProxy::Y)
488 .SetProperty("width", &WebAXObjectProxy::Width)
489 .SetProperty("height", &WebAXObjectProxy::Height)
490 .SetProperty("intValue", &WebAXObjectProxy::IntValue)
491 .SetProperty("minValue", &WebAXObjectProxy::MinValue)
492 .SetProperty("maxValue", &WebAXObjectProxy::MaxValue)
493 .SetProperty("valueDescription", &WebAXObjectProxy::ValueDescription)
494 .SetProperty("childrenCount", &WebAXObjectProxy::ChildrenCount)
495 .SetProperty("insertionPointLineNumber",
496 &WebAXObjectProxy::InsertionPointLineNumber)
497 .SetProperty("selectedTextRange", &WebAXObjectProxy::SelectedTextRange)
498 .SetProperty("isEnabled", &WebAXObjectProxy::IsEnabled)
499 .SetProperty("isRequired", &WebAXObjectProxy::IsRequired)
500 .SetProperty("isFocused", &WebAXObjectProxy::IsFocused)
501 .SetProperty("isFocusable", &WebAXObjectProxy::IsFocusable)
502 .SetProperty("isSelected", &WebAXObjectProxy::IsSelected)
503 .SetProperty("isSelectable", &WebAXObjectProxy::IsSelectable)
504 .SetProperty("isMultiSelectable", &WebAXObjectProxy::IsMultiSelectable)
505 .SetProperty("isSelectedOptionActive",
506 &WebAXObjectProxy::IsSelectedOptionActive)
507 .SetProperty("isExpanded", &WebAXObjectProxy::IsExpanded)
508 .SetProperty("isChecked", &WebAXObjectProxy::IsChecked)
509 .SetProperty("isVisible", &WebAXObjectProxy::IsVisible)
510 .SetProperty("isOffScreen", &WebAXObjectProxy::IsOffScreen)
511 .SetProperty("isCollapsed", &WebAXObjectProxy::IsCollapsed)
512 .SetProperty("hasPopup", &WebAXObjectProxy::HasPopup)
513 .SetProperty("isValid", &WebAXObjectProxy::IsValid)
514 .SetProperty("isReadOnly", &WebAXObjectProxy::IsReadOnly)
515 .SetProperty("orientation", &WebAXObjectProxy::Orientation)
516 .SetProperty("clickPointX", &WebAXObjectProxy::ClickPointX)
517 .SetProperty("clickPointY", &WebAXObjectProxy::ClickPointY)
518 .SetProperty("rowCount", &WebAXObjectProxy::RowCount)
519 .SetProperty("columnCount", &WebAXObjectProxy::ColumnCount)
520 .SetProperty("isClickable", &WebAXObjectProxy::IsClickable)
521 .SetMethod("allAttributes", &WebAXObjectProxy::AllAttributes)
522 .SetMethod("attributesOfChildren",
523 &WebAXObjectProxy::AttributesOfChildren)
524 .SetMethod("lineForIndex", &WebAXObjectProxy::LineForIndex)
525 .SetMethod("boundsForRange", &WebAXObjectProxy::BoundsForRange)
526 .SetMethod("childAtIndex", &WebAXObjectProxy::ChildAtIndex)
527 .SetMethod("elementAtPoint", &WebAXObjectProxy::ElementAtPoint)
528 .SetMethod("tableHeader", &WebAXObjectProxy::TableHeader)
529 .SetMethod("rowIndexRange", &WebAXObjectProxy::RowIndexRange)
530 .SetMethod("columnIndexRange", &WebAXObjectProxy::ColumnIndexRange)
531 .SetMethod("cellForColumnAndRow", &WebAXObjectProxy::CellForColumnAndRow)
532 .SetMethod("titleUIElement", &WebAXObjectProxy::TitleUIElement)
533 .SetMethod("setSelectedTextRange",
534 &WebAXObjectProxy::SetSelectedTextRange)
535 .SetMethod("isAttributeSettable", &WebAXObjectProxy::IsAttributeSettable)
536 .SetMethod("isPressActionSupported",
537 &WebAXObjectProxy::IsPressActionSupported)
538 .SetMethod("isIncrementActionSupported",
539 &WebAXObjectProxy::IsIncrementActionSupported)
540 .SetMethod("isDecrementActionSupported",
541 &WebAXObjectProxy::IsDecrementActionSupported)
542 .SetMethod("parentElement", &WebAXObjectProxy::ParentElement)
543 .SetMethod("increment", &WebAXObjectProxy::Increment)
544 .SetMethod("decrement", &WebAXObjectProxy::Decrement)
545 .SetMethod("showMenu", &WebAXObjectProxy::ShowMenu)
546 .SetMethod("press", &WebAXObjectProxy::Press)
547 .SetMethod("isEqual", &WebAXObjectProxy::IsEqual)
548 .SetMethod("setNotificationListener",
549 &WebAXObjectProxy::SetNotificationListener)
550 .SetMethod("unsetNotificationListener",
551 &WebAXObjectProxy::UnsetNotificationListener)
552 .SetMethod("takeFocus", &WebAXObjectProxy::TakeFocus)
553 .SetMethod("scrollToMakeVisible", &WebAXObjectProxy::ScrollToMakeVisible)
554 .SetMethod("scrollToMakeVisibleWithSubFocus",
555 &WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus)
556 .SetMethod("scrollToGlobalPoint", &WebAXObjectProxy::ScrollToGlobalPoint)
557 .SetMethod("wordStart", &WebAXObjectProxy::WordStart)
558 .SetMethod("wordEnd", &WebAXObjectProxy::WordEnd)
559 // TODO(hajimehoshi): This is for backward compatibility. Remove them.
560 .SetMethod("addNotificationListener",
561 &WebAXObjectProxy::SetNotificationListener)
562 .SetMethod("removeNotificationListener",
563 &WebAXObjectProxy::UnsetNotificationListener);
566 v8::Handle<v8::Object> WebAXObjectProxy::GetChildAtIndex(unsigned index) {
567 return factory_->GetOrCreate(accessibility_object_.childAt(index));
570 bool WebAXObjectProxy::IsRoot() const {
574 bool WebAXObjectProxy::IsEqualToObject(const blink::WebAXObject& other) {
575 return accessibility_object_.equals(other);
578 void WebAXObjectProxy::NotificationReceived(
579 blink::WebFrame* frame,
580 const std::string& notification_name) {
581 if (notification_callback_.IsEmpty())
584 v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
585 if (context.IsEmpty())
588 v8::Isolate* isolate = blink::mainThreadIsolate();
590 v8::Handle<v8::Value> argv[] = {
591 v8::String::NewFromUtf8(isolate, notification_name.data(),
592 v8::String::kNormalString,
593 notification_name.size()),
595 frame->callFunctionEvenIfScriptDisabled(
596 v8::Local<v8::Function>::New(isolate, notification_callback_),
602 void WebAXObjectProxy::Reset() {
603 notification_callback_.Reset();
606 std::string WebAXObjectProxy::Role() {
607 accessibility_object_.updateLayoutAndCheckValidity();
608 return GetRole(accessibility_object_);
611 std::string WebAXObjectProxy::Title() {
612 accessibility_object_.updateLayoutAndCheckValidity();
613 return GetTitle(accessibility_object_);
616 std::string WebAXObjectProxy::Description() {
617 accessibility_object_.updateLayoutAndCheckValidity();
618 return GetDescription(accessibility_object_);
621 std::string WebAXObjectProxy::HelpText() {
622 accessibility_object_.updateLayoutAndCheckValidity();
623 return GetHelpText(accessibility_object_);
626 std::string WebAXObjectProxy::StringValue() {
627 accessibility_object_.updateLayoutAndCheckValidity();
628 return GetStringValue(accessibility_object_);
631 int WebAXObjectProxy::X() {
632 accessibility_object_.updateLayoutAndCheckValidity();
633 return accessibility_object_.boundingBoxRect().x;
636 int WebAXObjectProxy::Y() {
637 accessibility_object_.updateLayoutAndCheckValidity();
638 return accessibility_object_.boundingBoxRect().y;
641 int WebAXObjectProxy::Width() {
642 accessibility_object_.updateLayoutAndCheckValidity();
643 return accessibility_object_.boundingBoxRect().width;
646 int WebAXObjectProxy::Height() {
647 accessibility_object_.updateLayoutAndCheckValidity();
648 return accessibility_object_.boundingBoxRect().height;
651 int WebAXObjectProxy::IntValue() {
652 accessibility_object_.updateLayoutAndCheckValidity();
653 if (accessibility_object_.supportsRangeValue())
654 return accessibility_object_.valueForRange();
655 else if (accessibility_object_.role() == blink::WebAXRoleHeading)
656 return accessibility_object_.headingLevel();
658 return atoi(accessibility_object_.stringValue().utf8().data());
661 int WebAXObjectProxy::MinValue() {
662 accessibility_object_.updateLayoutAndCheckValidity();
663 return accessibility_object_.minValueForRange();
666 int WebAXObjectProxy::MaxValue() {
667 accessibility_object_.updateLayoutAndCheckValidity();
668 return accessibility_object_.maxValueForRange();
671 std::string WebAXObjectProxy::ValueDescription() {
672 accessibility_object_.updateLayoutAndCheckValidity();
673 return GetValueDescription(accessibility_object_);
676 int WebAXObjectProxy::ChildrenCount() {
677 accessibility_object_.updateLayoutAndCheckValidity();
678 int count = 1; // Root object always has only one child, the WebView.
680 count = accessibility_object_.childCount();
684 int WebAXObjectProxy::InsertionPointLineNumber() {
685 accessibility_object_.updateLayoutAndCheckValidity();
686 if (!accessibility_object_.isFocused())
688 return accessibility_object_.selectionEndLineNumber();
691 std::string WebAXObjectProxy::SelectedTextRange() {
692 accessibility_object_.updateLayoutAndCheckValidity();
693 unsigned selection_start = accessibility_object_.selectionStart();
694 unsigned selection_end = accessibility_object_.selectionEnd();
695 return base::StringPrintf("{%d, %d}",
696 selection_start, selection_end - selection_start);
699 bool WebAXObjectProxy::IsEnabled() {
700 accessibility_object_.updateLayoutAndCheckValidity();
701 return accessibility_object_.isEnabled();
704 bool WebAXObjectProxy::IsRequired() {
705 accessibility_object_.updateLayoutAndCheckValidity();
706 return accessibility_object_.isRequired();
709 bool WebAXObjectProxy::IsFocused() {
710 accessibility_object_.updateLayoutAndCheckValidity();
711 return accessibility_object_.isFocused();
714 bool WebAXObjectProxy::IsFocusable() {
715 accessibility_object_.updateLayoutAndCheckValidity();
716 return accessibility_object_.canSetFocusAttribute();
719 bool WebAXObjectProxy::IsSelected() {
720 accessibility_object_.updateLayoutAndCheckValidity();
721 return accessibility_object_.isSelected();
724 bool WebAXObjectProxy::IsSelectable() {
725 accessibility_object_.updateLayoutAndCheckValidity();
726 return accessibility_object_.canSetSelectedAttribute();
729 bool WebAXObjectProxy::IsMultiSelectable() {
730 accessibility_object_.updateLayoutAndCheckValidity();
731 return accessibility_object_.isMultiSelectable();
734 bool WebAXObjectProxy::IsSelectedOptionActive() {
735 accessibility_object_.updateLayoutAndCheckValidity();
736 return accessibility_object_.isSelectedOptionActive();
739 bool WebAXObjectProxy::IsExpanded() {
740 accessibility_object_.updateLayoutAndCheckValidity();
741 return !accessibility_object_.isCollapsed();
744 bool WebAXObjectProxy::IsChecked() {
745 accessibility_object_.updateLayoutAndCheckValidity();
746 return accessibility_object_.isChecked();
749 bool WebAXObjectProxy::IsVisible() {
750 accessibility_object_.updateLayoutAndCheckValidity();
751 return accessibility_object_.isVisible();
754 bool WebAXObjectProxy::IsOffScreen() {
755 accessibility_object_.updateLayoutAndCheckValidity();
756 return accessibility_object_.isOffScreen();
759 bool WebAXObjectProxy::IsCollapsed() {
760 accessibility_object_.updateLayoutAndCheckValidity();
761 return accessibility_object_.isCollapsed();
764 bool WebAXObjectProxy::HasPopup() {
765 accessibility_object_.updateLayoutAndCheckValidity();
766 return accessibility_object_.ariaHasPopup();
769 bool WebAXObjectProxy::IsValid() {
770 accessibility_object_.updateLayoutAndCheckValidity();
771 return !accessibility_object_.isDetached();
774 bool WebAXObjectProxy::IsReadOnly() {
775 accessibility_object_.updateLayoutAndCheckValidity();
776 return accessibility_object_.isReadOnly();
779 std::string WebAXObjectProxy::Orientation() {
780 accessibility_object_.updateLayoutAndCheckValidity();
781 return GetOrientation(accessibility_object_);
784 int WebAXObjectProxy::ClickPointX() {
785 accessibility_object_.updateLayoutAndCheckValidity();
786 return accessibility_object_.clickPoint().x;
789 int WebAXObjectProxy::ClickPointY() {
790 accessibility_object_.updateLayoutAndCheckValidity();
791 return accessibility_object_.clickPoint().y;
794 int32_t WebAXObjectProxy::RowCount() {
795 accessibility_object_.updateLayoutAndCheckValidity();
796 return static_cast<int32_t>(accessibility_object_.rowCount());
799 int32_t WebAXObjectProxy::ColumnCount() {
800 accessibility_object_.updateLayoutAndCheckValidity();
801 return static_cast<int32_t>(accessibility_object_.columnCount());
804 bool WebAXObjectProxy::IsClickable() {
805 accessibility_object_.updateLayoutAndCheckValidity();
806 return accessibility_object_.isClickable();
809 std::string WebAXObjectProxy::AllAttributes() {
810 accessibility_object_.updateLayoutAndCheckValidity();
811 return GetAttributes(accessibility_object_);
814 std::string WebAXObjectProxy::AttributesOfChildren() {
815 accessibility_object_.updateLayoutAndCheckValidity();
816 AttributesCollector collector;
817 unsigned size = accessibility_object_.childCount();
818 for (unsigned i = 0; i < size; ++i)
819 collector.CollectAttributes(accessibility_object_.childAt(i));
820 return collector.attributes();
823 int WebAXObjectProxy::LineForIndex(int index) {
824 accessibility_object_.updateLayoutAndCheckValidity();
825 blink::WebVector<int> line_breaks;
826 accessibility_object_.lineBreaks(line_breaks);
828 int vector_size = static_cast<int>(line_breaks.size());
829 while (line < vector_size && line_breaks[line] <= index)
834 std::string WebAXObjectProxy::BoundsForRange(int start, int end) {
835 accessibility_object_.updateLayoutAndCheckValidity();
836 if (accessibility_object_.role() != blink::WebAXRoleStaticText)
837 return std::string();
839 if (!accessibility_object_.updateLayoutAndCheckValidity())
840 return std::string();
842 int len = end - start;
844 // Get the bounds for each character and union them into one large rectangle.
845 // This is just for testing so it doesn't need to be efficient.
846 blink::WebRect bounds = BoundsForCharacter(accessibility_object_, start);
847 for (int i = 1; i < len; i++) {
848 blink::WebRect next = BoundsForCharacter(accessibility_object_, start + i);
849 int right = std::max(bounds.x + bounds.width, next.x + next.width);
850 int bottom = std::max(bounds.y + bounds.height, next.y + next.height);
851 bounds.x = std::min(bounds.x, next.x);
852 bounds.y = std::min(bounds.y, next.y);
853 bounds.width = right - bounds.x;
854 bounds.height = bottom - bounds.y;
857 return base::StringPrintf("{x: %d, y: %d, width: %d, height: %d}",
858 bounds.x, bounds.y, bounds.width, bounds.height);
861 v8::Handle<v8::Object> WebAXObjectProxy::ChildAtIndex(int index) {
862 accessibility_object_.updateLayoutAndCheckValidity();
863 return GetChildAtIndex(index);
866 v8::Handle<v8::Object> WebAXObjectProxy::ElementAtPoint(int x, int y) {
867 accessibility_object_.updateLayoutAndCheckValidity();
868 blink::WebPoint point(x, y);
869 blink::WebAXObject obj = accessibility_object_.hitTest(point);
871 return v8::Handle<v8::Object>();
873 return factory_->GetOrCreate(obj);
876 v8::Handle<v8::Object> WebAXObjectProxy::TableHeader() {
877 accessibility_object_.updateLayoutAndCheckValidity();
878 blink::WebAXObject obj = accessibility_object_.headerContainerObject();
880 return v8::Handle<v8::Object>();
882 return factory_->GetOrCreate(obj);
885 std::string WebAXObjectProxy::RowIndexRange() {
886 accessibility_object_.updateLayoutAndCheckValidity();
887 unsigned row_index = accessibility_object_.cellRowIndex();
888 unsigned row_span = accessibility_object_.cellRowSpan();
889 return base::StringPrintf("{%d, %d}", row_index, row_span);
892 std::string WebAXObjectProxy::ColumnIndexRange() {
893 accessibility_object_.updateLayoutAndCheckValidity();
894 unsigned column_index = accessibility_object_.cellColumnIndex();
895 unsigned column_span = accessibility_object_.cellColumnSpan();
896 return base::StringPrintf("{%d, %d}", column_index, column_span);
899 v8::Handle<v8::Object> WebAXObjectProxy::CellForColumnAndRow(
900 int column, int row) {
901 accessibility_object_.updateLayoutAndCheckValidity();
902 blink::WebAXObject obj =
903 accessibility_object_.cellForColumnAndRow(column, row);
905 return v8::Handle<v8::Object>();
907 return factory_->GetOrCreate(obj);
910 v8::Handle<v8::Object> WebAXObjectProxy::TitleUIElement() {
911 accessibility_object_.updateLayoutAndCheckValidity();
912 blink::WebAXObject obj = accessibility_object_.titleUIElement();
914 return v8::Handle<v8::Object>();
916 return factory_->GetOrCreate(obj);
919 void WebAXObjectProxy::SetSelectedTextRange(int selection_start,
921 accessibility_object_.updateLayoutAndCheckValidity();
922 accessibility_object_.setSelectedTextRange(selection_start,
923 selection_start + length);
926 bool WebAXObjectProxy::IsAttributeSettable(const std::string& attribute) {
927 accessibility_object_.updateLayoutAndCheckValidity();
928 bool settable = false;
929 if (attribute == "AXValue")
930 settable = accessibility_object_.canSetValueAttribute();
934 bool WebAXObjectProxy::IsPressActionSupported() {
935 accessibility_object_.updateLayoutAndCheckValidity();
936 return accessibility_object_.canPress();
939 bool WebAXObjectProxy::IsIncrementActionSupported() {
940 accessibility_object_.updateLayoutAndCheckValidity();
941 return accessibility_object_.canIncrement();
944 bool WebAXObjectProxy::IsDecrementActionSupported() {
945 accessibility_object_.updateLayoutAndCheckValidity();
946 return accessibility_object_.canDecrement();
949 v8::Handle<v8::Object> WebAXObjectProxy::ParentElement() {
950 accessibility_object_.updateLayoutAndCheckValidity();
951 blink::WebAXObject parent_object = accessibility_object_.parentObject();
952 while (parent_object.accessibilityIsIgnored())
953 parent_object = parent_object.parentObject();
954 return factory_->GetOrCreate(parent_object);
957 void WebAXObjectProxy::Increment() {
958 accessibility_object_.updateLayoutAndCheckValidity();
959 accessibility_object_.increment();
962 void WebAXObjectProxy::Decrement() {
963 accessibility_object_.updateLayoutAndCheckValidity();
964 accessibility_object_.decrement();
967 void WebAXObjectProxy::ShowMenu() {
970 void WebAXObjectProxy::Press() {
971 accessibility_object_.updateLayoutAndCheckValidity();
972 accessibility_object_.press();
975 bool WebAXObjectProxy::IsEqual(v8::Handle<v8::Object> proxy) {
976 WebAXObjectProxy* unwrapped_proxy = NULL;
977 if (!gin::ConvertFromV8(blink::mainThreadIsolate(), proxy, &unwrapped_proxy))
979 return unwrapped_proxy->IsEqualToObject(accessibility_object_);
982 void WebAXObjectProxy::SetNotificationListener(
983 v8::Handle<v8::Function> callback) {
984 v8::Isolate* isolate = blink::mainThreadIsolate();
985 notification_callback_.Reset(isolate, callback);
988 void WebAXObjectProxy::UnsetNotificationListener() {
989 notification_callback_.Reset();
992 void WebAXObjectProxy::TakeFocus() {
993 accessibility_object_.updateLayoutAndCheckValidity();
994 accessibility_object_.setFocused(true);
997 void WebAXObjectProxy::ScrollToMakeVisible() {
998 accessibility_object_.updateLayoutAndCheckValidity();
999 accessibility_object_.scrollToMakeVisible();
1002 void WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus(int x, int y,
1003 int width, int height) {
1004 accessibility_object_.updateLayoutAndCheckValidity();
1005 accessibility_object_.scrollToMakeVisibleWithSubFocus(
1006 blink::WebRect(x, y, width, height));
1009 void WebAXObjectProxy::ScrollToGlobalPoint(int x, int y) {
1010 accessibility_object_.updateLayoutAndCheckValidity();
1011 accessibility_object_.scrollToGlobalPoint(blink::WebPoint(x, y));
1014 int WebAXObjectProxy::WordStart(int character_index) {
1015 accessibility_object_.updateLayoutAndCheckValidity();
1016 if (accessibility_object_.role() != blink::WebAXRoleStaticText)
1019 int word_start, word_end;
1020 GetBoundariesForOneWord(accessibility_object_, character_index,
1021 word_start, word_end);
1025 int WebAXObjectProxy::WordEnd(int character_index) {
1026 accessibility_object_.updateLayoutAndCheckValidity();
1027 if (accessibility_object_.role() != blink::WebAXRoleStaticText)
1030 int word_start, word_end;
1031 GetBoundariesForOneWord(accessibility_object_, character_index,
1032 word_start, word_end);
1036 RootWebAXObjectProxy::RootWebAXObjectProxy(
1037 const blink::WebAXObject &object, Factory *factory)
1038 : WebAXObjectProxy(object, factory) {
1041 v8::Handle<v8::Object> RootWebAXObjectProxy::GetChildAtIndex(unsigned index) {
1043 return v8::Handle<v8::Object>();
1045 return factory()->GetOrCreate(accessibility_object());
1048 bool RootWebAXObjectProxy::IsRoot() const {
1052 WebAXObjectProxyList::WebAXObjectProxyList()
1053 : elements_(blink::mainThreadIsolate()) {
1056 WebAXObjectProxyList::~WebAXObjectProxyList() {
1060 void WebAXObjectProxyList::Clear() {
1061 v8::Isolate* isolate = blink::mainThreadIsolate();
1062 v8::HandleScope handle_scope(isolate);
1063 size_t elementCount = elements_.Size();
1064 for (size_t i = 0; i < elementCount; i++) {
1065 WebAXObjectProxy* unwrapped_object = NULL;
1066 bool result = gin::ConvertFromV8(isolate, elements_.Get(i),
1069 DCHECK(unwrapped_object);
1070 unwrapped_object->Reset();
1075 v8::Handle<v8::Object> WebAXObjectProxyList::GetOrCreate(
1076 const blink::WebAXObject& object) {
1077 if (object.isNull())
1078 return v8::Handle<v8::Object>();
1080 v8::Isolate* isolate = blink::mainThreadIsolate();
1082 size_t elementCount = elements_.Size();
1083 for (size_t i = 0; i < elementCount; i++) {
1084 WebAXObjectProxy* unwrapped_object = NULL;
1085 bool result = gin::ConvertFromV8(isolate, elements_.Get(i),
1088 DCHECK(unwrapped_object);
1089 if (unwrapped_object->IsEqualToObject(object))
1090 return elements_.Get(i);
1093 v8::Handle<v8::Value> value_handle = gin::CreateHandle(
1094 isolate, new WebAXObjectProxy(object, this)).ToV8();
1095 if (value_handle.IsEmpty())
1096 return v8::Handle<v8::Object>();
1097 v8::Handle<v8::Object> handle = value_handle->ToObject();
1098 elements_.Append(handle);
1102 v8::Handle<v8::Object> WebAXObjectProxyList::CreateRoot(
1103 const blink::WebAXObject& object) {
1104 v8::Isolate* isolate = blink::mainThreadIsolate();
1105 v8::Handle<v8::Value> value_handle = gin::CreateHandle(
1106 isolate, new RootWebAXObjectProxy(object, this)).ToV8();
1107 if (value_handle.IsEmpty())
1108 return v8::Handle<v8::Object>();
1109 v8::Handle<v8::Object> handle = value_handle->ToObject();
1110 elements_.Append(handle);
1114 } // namespace content