Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Side by Side Diff: content/shell/renderer/test_runner/web_ax_object_proxy.cc

Issue 172263002: Move WebAXObjectProxy and AccessibleController from CppBoundClass to gin::Wrappable (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: (rebasing) Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // TODO(hajimehoshi): Remove this when UnsafePersistent is removed.
6 #define V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR
7
8 #include "content/shell/renderer/test_runner/web_ax_object_proxy.h"
9
10 #include "gin/handle.h"
11 #include "third_party/WebKit/public/platform/WebPoint.h"
12 #include "third_party/WebKit/public/platform/WebRect.h"
13 #include "third_party/WebKit/public/platform/WebString.h"
14 #include "third_party/WebKit/public/web/WebFrame.h"
15 #include "third_party/WebKit/public/web/WebKit.h"
16
17 namespace content {
18
19 namespace {
20
21 // Map role value to string, matching Safari/Mac platform implementation to
22 // avoid rebaselining layout tests.
23 std::string RoleToString(blink::WebAXRole role)
24 {
25 std::string result = "AXRole: AX";
26 switch (role) {
27 case blink::WebAXRoleAlertDialog:
28 return result.append("AlertDialog");
29 case blink::WebAXRoleAlert:
30 return result.append("Alert");
31 case blink::WebAXRoleAnnotation:
32 return result.append("Annotation");
33 case blink::WebAXRoleApplication:
34 return result.append("Application");
35 case blink::WebAXRoleArticle:
36 return result.append("Article");
37 case blink::WebAXRoleBanner:
38 return result.append("Banner");
39 case blink::WebAXRoleBrowser:
40 return result.append("Browser");
41 case blink::WebAXRoleBusyIndicator:
42 return result.append("BusyIndicator");
43 case blink::WebAXRoleButton:
44 return result.append("Button");
45 case blink::WebAXRoleCanvas:
46 return result.append("Canvas");
47 case blink::WebAXRoleCell:
48 return result.append("Cell");
49 case blink::WebAXRoleCheckBox:
50 return result.append("CheckBox");
51 case blink::WebAXRoleColorWell:
52 return result.append("ColorWell");
53 case blink::WebAXRoleColumnHeader:
54 return result.append("ColumnHeader");
55 case blink::WebAXRoleColumn:
56 return result.append("Column");
57 case blink::WebAXRoleComboBox:
58 return result.append("ComboBox");
59 case blink::WebAXRoleComplementary:
60 return result.append("Complementary");
61 case blink::WebAXRoleContentInfo:
62 return result.append("ContentInfo");
63 case blink::WebAXRoleDefinition:
64 return result.append("Definition");
65 case blink::WebAXRoleDescriptionListDetail:
66 return result.append("DescriptionListDetail");
67 case blink::WebAXRoleDescriptionListTerm:
68 return result.append("DescriptionListTerm");
69 case blink::WebAXRoleDialog:
70 return result.append("Dialog");
71 case blink::WebAXRoleDirectory:
72 return result.append("Directory");
73 case blink::WebAXRoleDisclosureTriangle:
74 return result.append("DisclosureTriangle");
75 case blink::WebAXRoleDiv:
76 return result.append("Div");
77 case blink::WebAXRoleDocument:
78 return result.append("Document");
79 case blink::WebAXRoleDrawer:
80 return result.append("Drawer");
81 case blink::WebAXRoleEditableText:
82 return result.append("EditableText");
83 case blink::WebAXRoleFooter:
84 return result.append("Footer");
85 case blink::WebAXRoleForm:
86 return result.append("Form");
87 case blink::WebAXRoleGrid:
88 return result.append("Grid");
89 case blink::WebAXRoleGroup:
90 return result.append("Group");
91 case blink::WebAXRoleGrowArea:
92 return result.append("GrowArea");
93 case blink::WebAXRoleHeading:
94 return result.append("Heading");
95 case blink::WebAXRoleHelpTag:
96 return result.append("HelpTag");
97 case blink::WebAXRoleHorizontalRule:
98 return result.append("HorizontalRule");
99 case blink::WebAXRoleIgnored:
100 return result.append("Ignored");
101 case blink::WebAXRoleImageMapLink:
102 return result.append("ImageMapLink");
103 case blink::WebAXRoleImageMap:
104 return result.append("ImageMap");
105 case blink::WebAXRoleImage:
106 return result.append("Image");
107 case blink::WebAXRoleIncrementor:
108 return result.append("Incrementor");
109 case blink::WebAXRoleInlineTextBox:
110 return result.append("InlineTextBox");
111 case blink::WebAXRoleLabel:
112 return result.append("Label");
113 case blink::WebAXRoleLegend:
114 return result.append("Legend");
115 case blink::WebAXRoleLink:
116 return result.append("Link");
117 case blink::WebAXRoleListBoxOption:
118 return result.append("ListBoxOption");
119 case blink::WebAXRoleListBox:
120 return result.append("ListBox");
121 case blink::WebAXRoleListItem:
122 return result.append("ListItem");
123 case blink::WebAXRoleListMarker:
124 return result.append("ListMarker");
125 case blink::WebAXRoleList:
126 return result.append("List");
127 case blink::WebAXRoleLog:
128 return result.append("Log");
129 case blink::WebAXRoleMain:
130 return result.append("Main");
131 case blink::WebAXRoleMarquee:
132 return result.append("Marquee");
133 case blink::WebAXRoleMathElement:
134 return result.append("MathElement");
135 case blink::WebAXRoleMath:
136 return result.append("Math");
137 case blink::WebAXRoleMatte:
138 return result.append("Matte");
139 case blink::WebAXRoleMenuBar:
140 return result.append("MenuBar");
141 case blink::WebAXRoleMenuButton:
142 return result.append("MenuButton");
143 case blink::WebAXRoleMenuItem:
144 return result.append("MenuItem");
145 case blink::WebAXRoleMenuListOption:
146 return result.append("MenuListOption");
147 case blink::WebAXRoleMenuListPopup:
148 return result.append("MenuListPopup");
149 case blink::WebAXRoleMenu:
150 return result.append("Menu");
151 case blink::WebAXRoleNavigation:
152 return result.append("Navigation");
153 case blink::WebAXRoleNote:
154 return result.append("Note");
155 case blink::WebAXRoleOutline:
156 return result.append("Outline");
157 case blink::WebAXRoleParagraph:
158 return result.append("Paragraph");
159 case blink::WebAXRolePopUpButton:
160 return result.append("PopUpButton");
161 case blink::WebAXRolePresentational:
162 return result.append("Presentational");
163 case blink::WebAXRoleProgressIndicator:
164 return result.append("ProgressIndicator");
165 case blink::WebAXRoleRadioButton:
166 return result.append("RadioButton");
167 case blink::WebAXRoleRadioGroup:
168 return result.append("RadioGroup");
169 case blink::WebAXRoleRegion:
170 return result.append("Region");
171 case blink::WebAXRoleRootWebArea:
172 return result.append("RootWebArea");
173 case blink::WebAXRoleRowHeader:
174 return result.append("RowHeader");
175 case blink::WebAXRoleRow:
176 return result.append("Row");
177 case blink::WebAXRoleRulerMarker:
178 return result.append("RulerMarker");
179 case blink::WebAXRoleRuler:
180 return result.append("Ruler");
181 case blink::WebAXRoleSVGRoot:
182 return result.append("SVGRoot");
183 case blink::WebAXRoleScrollArea:
184 return result.append("ScrollArea");
185 case blink::WebAXRoleScrollBar:
186 return result.append("ScrollBar");
187 case blink::WebAXRoleSeamlessWebArea:
188 return result.append("SeamlessWebArea");
189 case blink::WebAXRoleSearch:
190 return result.append("Search");
191 case blink::WebAXRoleSheet:
192 return result.append("Sheet");
193 case blink::WebAXRoleSlider:
194 return result.append("Slider");
195 case blink::WebAXRoleSliderThumb:
196 return result.append("SliderThumb");
197 case blink::WebAXRoleSpinButtonPart:
198 return result.append("SpinButtonPart");
199 case blink::WebAXRoleSpinButton:
200 return result.append("SpinButton");
201 case blink::WebAXRoleSplitGroup:
202 return result.append("SplitGroup");
203 case blink::WebAXRoleSplitter:
204 return result.append("Splitter");
205 case blink::WebAXRoleStaticText:
206 return result.append("StaticText");
207 case blink::WebAXRoleStatus:
208 return result.append("Status");
209 case blink::WebAXRoleSystemWide:
210 return result.append("SystemWide");
211 case blink::WebAXRoleTabGroup:
212 return result.append("TabGroup");
213 case blink::WebAXRoleTabList:
214 return result.append("TabList");
215 case blink::WebAXRoleTabPanel:
216 return result.append("TabPanel");
217 case blink::WebAXRoleTab:
218 return result.append("Tab");
219 case blink::WebAXRoleTableHeaderContainer:
220 return result.append("TableHeaderContainer");
221 case blink::WebAXRoleTable:
222 return result.append("Table");
223 case blink::WebAXRoleTextArea:
224 return result.append("TextArea");
225 case blink::WebAXRoleTextField:
226 return result.append("TextField");
227 case blink::WebAXRoleTimer:
228 return result.append("Timer");
229 case blink::WebAXRoleToggleButton:
230 return result.append("ToggleButton");
231 case blink::WebAXRoleToolbar:
232 return result.append("Toolbar");
233 case blink::WebAXRoleTreeGrid:
234 return result.append("TreeGrid");
235 case blink::WebAXRoleTreeItem:
236 return result.append("TreeItem");
237 case blink::WebAXRoleTree:
238 return result.append("Tree");
239 case blink::WebAXRoleUnknown:
240 return result.append("Unknown");
241 case blink::WebAXRoleUserInterfaceTooltip:
242 return result.append("UserInterfaceTooltip");
243 case blink::WebAXRoleValueIndicator:
244 return result.append("ValueIndicator");
245 case blink::WebAXRoleWebArea:
246 return result.append("WebArea");
247 case blink::WebAXRoleWindow:
248 return result.append("Window");
249 default:
250 return result.append("Unknown");
251 }
252 }
253
254 std::string GetDescription(const blink::WebAXObject& object) {
255 std::string description = object.accessibilityDescription().utf8();
256 return description.insert(0, "AXDescription: ");
257 }
258
259 std::string GetHelpText(const blink::WebAXObject& object) {
260 std::string help_text = object.helpText().utf8();
261 return help_text.insert(0, "AXHelp: ");
262 }
263
264 std::string GetStringValue(const blink::WebAXObject& object) {
265 std::string value;
266 if (object.role() == blink::WebAXRoleColorWell) {
267 int r, g, b;
268 char buffer[100];
269 object.colorValue(r, g, b);
270 snprintf(buffer, sizeof(buffer), "rgb %7.5f %7.5f %7.5f 1",
271 r / 255., g / 255., b / 255.);
272 value = buffer;
273 } else {
274 value = object.stringValue().utf8();
275 }
276 return value.insert(0, "AXValue: ");
277 }
278
279 std::string GetRole(const blink::WebAXObject& object) {
280 std::string role_string = RoleToString(object.role());
281
282 // Special-case canvas with fallback content because Chromium wants to treat
283 // this as essentially a separate role that it can map differently depending
284 // on the platform.
285 if (object.role() == blink::WebAXRoleCanvas &&
286 object.canvasHasFallbackContent()) {
287 role_string += "WithFallbackContent";
288 }
289
290 return role_string;
291 }
292
293 std::string GetTitle(const blink::WebAXObject& object) {
294 std::string title = object.title().utf8();
295 return title.insert(0, "AXTitle: ");
296 }
297
298 std::string GetOrientation(const blink::WebAXObject& object) {
299 if (object.isVertical())
300 return "AXOrientation: AXVerticalOrientation";
301
302 return "AXOrientation: AXHorizontalOrientation";
303 }
304
305 std::string GetValueDescription(const blink::WebAXObject& object) {
306 std::string value_description = object.valueDescription().utf8();
307 return value_description.insert(0, "AXValueDescription: ");
308 }
309
310 std::string GetAttributes(const blink::WebAXObject& object) {
311 // FIXME: Concatenate all attributes of the AXObject.
312 std::string attributes(GetTitle(object));
313 attributes.append("\n");
314 attributes.append(GetRole(object));
315 attributes.append("\n");
316 attributes.append(GetDescription(object));
317 return attributes;
318 }
319
320 blink::WebRect BoundsForCharacter(const blink::WebAXObject& object,
321 int characterIndex) {
322 DCHECK_EQ(object.role(), blink::WebAXRoleStaticText);
323 int end = 0;
324 for (unsigned i = 0; i < object.childCount(); i++) {
325 blink::WebAXObject inline_text_box = object.childAt(i);
326 DCHECK_EQ(inline_text_box.role(), blink::WebAXRoleInlineTextBox);
327 int start = end;
328 end += inline_text_box.stringValue().length();
329 if (end <= characterIndex)
330 continue;
331 blink::WebRect inline_text_box_rect = inline_text_box.boundingBoxRect();
332 int localIndex = characterIndex - start;
333 blink::WebVector<int> character_offsets;
334 inline_text_box.characterOffsets(character_offsets);
335 DCHECK(character_offsets.size() > 0 &&
336 character_offsets.size() == inline_text_box.stringValue().length());
337 switch (inline_text_box.textDirection()) {
338 case blink::WebAXTextDirectionLR: {
339 if (localIndex) {
340 int left = inline_text_box_rect.x + character_offsets[localIndex - 1];
341 int width = character_offsets[localIndex] -
342 character_offsets[localIndex - 1];
343 return blink::WebRect(left, inline_text_box_rect.y,
344 width, inline_text_box_rect.height);
345 }
346 return blink::WebRect(
347 inline_text_box_rect.x, inline_text_box_rect.y,
348 character_offsets[0], inline_text_box_rect.height);
349 }
350 case blink::WebAXTextDirectionRL: {
351 int right = inline_text_box_rect.x + inline_text_box_rect.width;
352
353 if (localIndex) {
354 int left = right - character_offsets[localIndex];
355 int width = character_offsets[localIndex] -
356 character_offsets[localIndex - 1];
357 return blink::WebRect(left, inline_text_box_rect.y,
358 width, inline_text_box_rect.height);
359 }
360 int left = right - character_offsets[0];
361 return blink::WebRect(
362 left, inline_text_box_rect.y,
363 character_offsets[0], inline_text_box_rect.height);
364 }
365 case blink::WebAXTextDirectionTB: {
366 if (localIndex) {
367 int top = inline_text_box_rect.y + character_offsets[localIndex - 1];
368 int height = character_offsets[localIndex] -
369 character_offsets[localIndex - 1];
370 return blink::WebRect(inline_text_box_rect.x, top,
371 inline_text_box_rect.width, height);
372 }
373 return blink::WebRect(inline_text_box_rect.x, inline_text_box_rect.y,
374 inline_text_box_rect.width, character_offsets[0]);
375 }
376 case blink::WebAXTextDirectionBT: {
377 int bottom = inline_text_box_rect.y + inline_text_box_rect.height;
378
379 if (localIndex) {
380 int top = bottom - character_offsets[localIndex];
381 int height = character_offsets[localIndex] -
382 character_offsets[localIndex - 1];
383 return blink::WebRect(inline_text_box_rect.x, top,
384 inline_text_box_rect.width, height);
385 }
386 int top = bottom - character_offsets[0];
387 return blink::WebRect(inline_text_box_rect.x, top,
388 inline_text_box_rect.width, character_offsets[0]);
389 }
390 }
391 }
392
393 DCHECK(false);
394 return blink::WebRect();
395 }
396
397 void GetBoundariesForOneWord(const blink::WebAXObject& object,
398 int character_index,
399 int& word_start,
400 int& word_end) {
401 int end = 0;
402 for (unsigned i = 0; i < object.childCount(); i++) {
403 blink::WebAXObject inline_text_box = object.childAt(i);
404 DCHECK_EQ(inline_text_box.role(), blink::WebAXRoleInlineTextBox);
405 int start = end;
406 end += inline_text_box.stringValue().length();
407 if (end <= character_index)
408 continue;
409 int localIndex = character_index - start;
410
411 blink::WebVector<int> starts;
412 blink::WebVector<int> ends;
413 inline_text_box.wordBoundaries(starts, ends);
414 size_t word_count = starts.size();
415 DCHECK_EQ(ends.size(), word_count);
416
417 // If there are no words, use the InlineTextBox boundaries.
418 if (!word_count) {
419 word_start = start;
420 word_end = end;
421 return;
422 }
423
424 // Look for a character within any word other than the last.
425 for (size_t j = 0; j < word_count - 1; j++) {
426 if (localIndex <= ends[j]) {
427 word_start = start + starts[j];
428 word_end = start + ends[j];
429 return;
430 }
431 }
432
433 // Return the last word by default.
434 word_start = start + starts[word_count - 1];
435 word_end = start + ends[word_count - 1];
436 return;
437 }
438 }
439
440 // Collects attributes into a string, delimited by dashes. Used by all methods
441 // that output lists of attributes: attributesOfLinkedUIElementsCallback,
442 // AttributesOfChildrenCallback, etc.
443 class AttributesCollector {
444 public:
445 AttributesCollector() {}
446 ~AttributesCollector() {}
447
448 void CollectAttributes(const blink::WebAXObject& object) {
449 attributes_.append("\n------------\n");
450 attributes_.append(GetAttributes(object));
451 }
452
453 std::string attributes() const { return attributes_; }
454
455 private:
456 std::string attributes_;
457
458 DISALLOW_COPY_AND_ASSIGN(AttributesCollector);
459 };
460
461 } // namespace
462
463 gin::WrapperInfo WebAXObjectProxy::kWrapperInfo = {
464 gin::kEmbedderNativeGin};
465
466 WebAXObjectProxy::WebAXObjectProxy(const blink::WebAXObject& object,
467 WebAXObjectProxy::Factory* factory)
468 : accessibility_object_(object),
469 factory_(factory) {
470 }
471
472 WebAXObjectProxy::~WebAXObjectProxy() {
473 ClearNotificationCallbacks();
474 }
475
476 gin::ObjectTemplateBuilder
477 WebAXObjectProxy::GetObjectTemplateBuilder(v8::Isolate* isolate) {
478 return gin::Wrappable<WebAXObjectProxy>::GetObjectTemplateBuilder(isolate)
479 .SetProperty("role", &WebAXObjectProxy::Role)
480 .SetProperty("title", &WebAXObjectProxy::Title)
481 .SetProperty("description", &WebAXObjectProxy::Description)
482 .SetProperty("helpText", &WebAXObjectProxy::HelpText)
483 .SetProperty("stringValue", &WebAXObjectProxy::StringValue)
484 .SetProperty("x", &WebAXObjectProxy::X)
485 .SetProperty("y", &WebAXObjectProxy::Y)
486 .SetProperty("width", &WebAXObjectProxy::Width)
487 .SetProperty("height", &WebAXObjectProxy::Height)
488 .SetProperty("intValue", &WebAXObjectProxy::IntValue)
489 .SetProperty("minValue", &WebAXObjectProxy::MinValue)
490 .SetProperty("maxValue", &WebAXObjectProxy::MaxValue)
491 .SetProperty("valueDescription", &WebAXObjectProxy::ValueDescription)
492 .SetProperty("childrenCount", &WebAXObjectProxy::ChildrenCount)
493 .SetProperty("insertionPointLineNumber",
494 &WebAXObjectProxy::InsertionPointLineNumber)
495 .SetProperty("selectedTextRange", &WebAXObjectProxy::SelectedTextRange)
496 .SetProperty("isEnabled", &WebAXObjectProxy::IsEnabled)
497 .SetProperty("isRequired", &WebAXObjectProxy::IsRequired)
498 .SetProperty("isFocused", &WebAXObjectProxy::IsFocused)
499 .SetProperty("isFocusable", &WebAXObjectProxy::IsFocusable)
500 .SetProperty("isSelected", &WebAXObjectProxy::IsSelected)
501 .SetProperty("isSelectable", &WebAXObjectProxy::IsSelectable)
502 .SetProperty("isMultiSelectable", &WebAXObjectProxy::IsMultiSelectable)
503 .SetProperty("isSelectedOptionActive",
504 &WebAXObjectProxy::IsSelectedOptionActive)
505 .SetProperty("isExpanded", &WebAXObjectProxy::IsExpanded)
506 .SetProperty("isChecked", &WebAXObjectProxy::IsChecked)
507 .SetProperty("isVisible", &WebAXObjectProxy::IsVisible)
508 .SetProperty("isOffScreen", &WebAXObjectProxy::IsOffScreen)
509 .SetProperty("isCollapsed", &WebAXObjectProxy::IsCollapsed)
510 .SetProperty("hasPopup", &WebAXObjectProxy::HasPopup)
511 .SetProperty("isValid", &WebAXObjectProxy::IsValid)
512 .SetProperty("isReadOnly", &WebAXObjectProxy::IsReadOnly)
513 .SetProperty("orientation", &WebAXObjectProxy::Orientation)
514 .SetProperty("clickPointX", &WebAXObjectProxy::ClickPointX)
515 .SetProperty("clickPointY", &WebAXObjectProxy::ClickPointY)
516 .SetProperty("rowCount", &WebAXObjectProxy::RowCount)
517 .SetProperty("columnCount", &WebAXObjectProxy::ColumnCount)
518 .SetProperty("isClickable", &WebAXObjectProxy::IsClickable)
519 .SetMethod("allAttributes", &WebAXObjectProxy::AllAttributes)
520 .SetMethod("attributesOfChildren",
521 &WebAXObjectProxy::AttributesOfChildren)
522 .SetMethod("lineForIndex", &WebAXObjectProxy::LineForIndex)
523 .SetMethod("boundsForRange", &WebAXObjectProxy::BoundsForRange)
524 .SetMethod("childAtIndex", &WebAXObjectProxy::ChildAtIndex)
525 .SetMethod("elementAtPoint", &WebAXObjectProxy::ElementAtPoint)
526 .SetMethod("tableHeader", &WebAXObjectProxy::TableHeader)
527 .SetMethod("rowIndexRange", &WebAXObjectProxy::RowIndexRange)
528 .SetMethod("columnIndexRange", &WebAXObjectProxy::ColumnIndexRange)
529 .SetMethod("cellForColumnAndRow", &WebAXObjectProxy::CellForColumnAndRow)
530 .SetMethod("titleUIElement", &WebAXObjectProxy::TitleUIElement)
531 .SetMethod("setSelectedTextRange",
532 &WebAXObjectProxy::SetSelectedTextRange)
533 .SetMethod("isAttributeSettable", &WebAXObjectProxy::IsAttributeSettable)
534 .SetMethod("isPressActionSupported",
535 &WebAXObjectProxy::IsPressActionSupported)
536 .SetMethod("isIncrementActionSupported",
537 &WebAXObjectProxy::IsIncrementActionSupported)
538 .SetMethod("isDecrementActionSupported",
539 &WebAXObjectProxy::IsDecrementActionSupported)
540 .SetMethod("parentElement", &WebAXObjectProxy::ParentElement)
541 .SetMethod("increment", &WebAXObjectProxy::Increment)
542 .SetMethod("decrement", &WebAXObjectProxy::Decrement)
543 .SetMethod("showMenu", &WebAXObjectProxy::ShowMenu)
544 .SetMethod("press", &WebAXObjectProxy::Press)
545 .SetMethod("isEqual", &WebAXObjectProxy::IsEqual)
546 .SetMethod("addNotificationListener",
547 &WebAXObjectProxy::AddNotificationListener)
548 .SetMethod("removeNotificationListener",
549 &WebAXObjectProxy::RemoveNotificationListener)
550 .SetMethod("takeFocus", &WebAXObjectProxy::TakeFocus)
551 .SetMethod("scrollToMakeVisible", &WebAXObjectProxy::ScrollToMakeVisible)
552 .SetMethod("scrollToMakeVisibleWithSubFocus",
553 &WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus)
554 .SetMethod("scrollToGlobalPoint", &WebAXObjectProxy::ScrollToGlobalPoint)
555 .SetMethod("wordStart", &WebAXObjectProxy::WordStart)
556 .SetMethod("wordEnd", &WebAXObjectProxy::WordEnd);
557 }
558
559 v8::Handle<v8::Object> WebAXObjectProxy::GetChildAtIndex(unsigned index) {
560 return factory_->GetOrCreate(accessibility_object().childAt(index));
561 }
562
563 bool WebAXObjectProxy::IsRoot() const {
564 return false;
565 }
566
567 bool WebAXObjectProxy::IsEqualToObject(const blink::WebAXObject& other) {
568 return accessibility_object().equals(other);
569 }
570
571 void WebAXObjectProxy::NotificationReceived(
572 blink::WebFrame* frame,
573 const std::string& notification_name) {
574 v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
575 if (context.IsEmpty())
576 return;
577
578 v8::Isolate* isolate = blink::mainThreadIsolate();
579
580 v8::Handle<v8::Value> argv[] = {
581 v8::String::NewFromUtf8(isolate, notification_name.data(),
582 v8::String::kNormalString,
583 notification_name.size()),
584 };
585 for (CallbackList::iterator it = notification_callbacks_.begin();
586 it != notification_callbacks_.end(); ++it) {
587 frame->callFunctionEvenIfScriptDisabled((*it).NewLocal(isolate),
588 context->Global(),
589 arraysize(argv),
590 argv);
591 }
592 }
593
594 std::string WebAXObjectProxy::Role() {
595 return GetRole(accessibility_object());
596 }
597
598 std::string WebAXObjectProxy::Title() {
599 return GetTitle(accessibility_object());
600 }
601
602 std::string WebAXObjectProxy::Description() {
603 return GetDescription(accessibility_object());
604 }
605
606 std::string WebAXObjectProxy::HelpText() {
607 return GetHelpText(accessibility_object());
608 }
609
610 std::string WebAXObjectProxy::StringValue() {
611 return GetStringValue(accessibility_object());
612 }
613
614 int WebAXObjectProxy::X() {
615 return accessibility_object().boundingBoxRect().x;
616 }
617
618 int WebAXObjectProxy::Y() {
619 return accessibility_object().boundingBoxRect().y;
620 }
621
622 int WebAXObjectProxy::Width() {
623 return accessibility_object().boundingBoxRect().width;
624 }
625
626 int WebAXObjectProxy::Height() {
627 return accessibility_object().boundingBoxRect().height;
628 }
629
630 int WebAXObjectProxy::IntValue() {
631 if (accessibility_object().supportsRangeValue())
632 return accessibility_object().valueForRange();
633 else if (accessibility_object().role() == blink::WebAXRoleHeading)
634 return accessibility_object().headingLevel();
635 else
636 return atoi(accessibility_object().stringValue().utf8().data());
637 }
638
639 int WebAXObjectProxy::MinValue() {
640 return accessibility_object().minValueForRange();
641 }
642
643 int WebAXObjectProxy::MaxValue() {
644 return accessibility_object().maxValueForRange();
645 }
646
647 std::string WebAXObjectProxy::ValueDescription() {
648 return GetValueDescription(accessibility_object());
649 }
650
651 int WebAXObjectProxy::ChildrenCount() {
652 int count = 1; // Root object always has only one child, the WebView.
653 if (!IsRoot())
654 count = accessibility_object().childCount();
655 return count;
656 }
657
658 int WebAXObjectProxy::InsertionPointLineNumber() {
659 if (!accessibility_object().isFocused())
660 return -1;
661 return accessibility_object().selectionEndLineNumber();
662 }
663
664 std::string WebAXObjectProxy::SelectedTextRange() {
665 unsigned selection_start = accessibility_object().selectionStart();
666 unsigned selection_end = accessibility_object().selectionEnd();
667 char buffer[100];
668 snprintf(buffer, sizeof(buffer), "{%d, %d}",
669 selection_start, selection_end - selection_start);
670 return std::string(buffer);
671 }
672
673 bool WebAXObjectProxy::IsEnabled() {
674 return accessibility_object().isEnabled();
675 }
676
677 bool WebAXObjectProxy::IsRequired() {
678 return accessibility_object().isRequired();
679 }
680
681 bool WebAXObjectProxy::IsFocused() {
682 return accessibility_object().isFocused();
683 }
684
685 bool WebAXObjectProxy::IsFocusable() {
686 return accessibility_object().canSetFocusAttribute();
687 }
688
689 bool WebAXObjectProxy::IsSelected() {
690 return accessibility_object().isSelected();
691 }
692
693 bool WebAXObjectProxy::IsSelectable() {
694 return accessibility_object().canSetSelectedAttribute();
695 }
696
697 bool WebAXObjectProxy::IsMultiSelectable() {
698 return accessibility_object().isMultiSelectable();
699 }
700
701 bool WebAXObjectProxy::IsSelectedOptionActive() {
702 return accessibility_object().isSelectedOptionActive();
703 }
704
705 bool WebAXObjectProxy::IsExpanded() {
706 return !accessibility_object().isCollapsed();
707 }
708
709 bool WebAXObjectProxy::IsChecked() {
710 return accessibility_object().isChecked();
711 }
712
713 bool WebAXObjectProxy::IsVisible() {
714 return accessibility_object().isVisible();
715 }
716
717 bool WebAXObjectProxy::IsOffScreen() {
718 return accessibility_object().isOffScreen();
719 }
720
721 bool WebAXObjectProxy::IsCollapsed() {
722 return accessibility_object().isCollapsed();
723 }
724
725 bool WebAXObjectProxy::HasPopup() {
726 return accessibility_object().ariaHasPopup();
727 }
728
729 bool WebAXObjectProxy::IsValid() {
730 return !accessibility_object().isDetached();
731 }
732
733 bool WebAXObjectProxy::IsReadOnly() {
734 return accessibility_object().isReadOnly();
735 }
736
737 std::string WebAXObjectProxy::Orientation() {
738 return GetOrientation(accessibility_object());
739 }
740
741 int WebAXObjectProxy::ClickPointX() {
742 return accessibility_object().clickPoint().x;
743 }
744
745 int WebAXObjectProxy::ClickPointY() {
746 return accessibility_object().clickPoint().y;
747 }
748
749 int32_t WebAXObjectProxy::RowCount() {
750 return static_cast<int32_t>(accessibility_object().rowCount());
751 }
752
753 int32_t WebAXObjectProxy::ColumnCount() {
754 return static_cast<int32_t>(accessibility_object().columnCount());
755 }
756
757 bool WebAXObjectProxy::IsClickable() {
758 return accessibility_object().isClickable();
759 }
760
761 std::string WebAXObjectProxy::AllAttributes() {
762 return GetAttributes(accessibility_object());
763 }
764
765 std::string WebAXObjectProxy::AttributesOfChildren() {
766 AttributesCollector collector;
767 unsigned size = accessibility_object().childCount();
768 for (unsigned i = 0; i < size; ++i)
769 collector.CollectAttributes(accessibility_object().childAt(i));
770 return collector.attributes();
771 }
772
773 int WebAXObjectProxy::LineForIndex(int index) {
774 blink::WebVector<int> line_breaks;
775 accessibility_object().lineBreaks(line_breaks);
776 int line = 0;
777 int vector_size = static_cast<int>(line_breaks.size());
778 while (line < vector_size && line_breaks[line] <= index)
779 line++;
780 return line;
781 }
782
783 std::string WebAXObjectProxy::BoundsForRange(int start, int end) {
784 if (accessibility_object().role() != blink::WebAXRoleStaticText)
785 return std::string();
786
787 int len = end - start;
788
789 // Get the bounds for each character and union them into one large rectangle.
790 // This is just for testing so it doesn't need to be efficient.
791 blink::WebRect bounds = BoundsForCharacter(accessibility_object(), start);
792 for (int i = 1; i < len; i++) {
793 blink::WebRect next = BoundsForCharacter(accessibility_object(), start + i);
794 int right = std::max(bounds.x + bounds.width, next.x + next.width);
795 int bottom = std::max(bounds.y + bounds.height, next.y + next.height);
796 bounds.x = std::min(bounds.x, next.x);
797 bounds.y = std::min(bounds.y, next.y);
798 bounds.width = right - bounds.x;
799 bounds.height = bottom - bounds.y;
800 }
801
802 char buffer[100];
803 snprintf(buffer, sizeof(buffer), "{x: %d, y: %d, width: %d, height: %d}",
804 bounds.x, bounds.y, bounds.width, bounds.height);
805 return std::string(buffer);
806 }
807
808 v8::Handle<v8::Object> WebAXObjectProxy::ChildAtIndex(int index) {
809 return GetChildAtIndex(index);
810 }
811
812 v8::Handle<v8::Object> WebAXObjectProxy::ElementAtPoint(int x, int y) {
813 blink::WebPoint point(x, y);
814 blink::WebAXObject obj = accessibility_object().hitTest(point);
815 if (obj.isNull())
816 return v8::Handle<v8::Object>();
817
818 return factory_->GetOrCreate(obj);
819 }
820
821 v8::Handle<v8::Object> WebAXObjectProxy::TableHeader() {
822 blink::WebAXObject obj = accessibility_object().headerContainerObject();
823 if (obj.isNull())
824 return v8::Handle<v8::Object>();
825
826 return factory_->GetOrCreate(obj);
827 }
828
829 std::string WebAXObjectProxy::RowIndexRange() {
830 unsigned row_index = accessibility_object().cellRowIndex();
831 unsigned row_span = accessibility_object().cellRowSpan();
832 char buffer[100];
833 snprintf(buffer, sizeof(buffer), "{%d, %d}", row_index, row_span);
834 return std::string(buffer);
835 }
836
837 std::string WebAXObjectProxy::ColumnIndexRange() {
838 unsigned column_index = accessibility_object().cellColumnIndex();
839 unsigned column_span = accessibility_object().cellColumnSpan();
840 char buffer[100];
841 snprintf(buffer, sizeof(buffer), "{%d, %d}", column_index, column_span);
842 return std::string(buffer);
843 }
844
845 v8::Handle<v8::Object> WebAXObjectProxy::CellForColumnAndRow(
846 int column, int row) {
847 blink::WebAXObject obj =
848 accessibility_object().cellForColumnAndRow(column, row);
849 if (obj.isNull())
850 return v8::Handle<v8::Object>();
851
852 return factory_->GetOrCreate(obj);
853 }
854
855 v8::Handle<v8::Object> WebAXObjectProxy::TitleUIElement() {
856 blink::WebAXObject obj = accessibility_object().titleUIElement();
857 if (obj.isNull())
858 return v8::Handle<v8::Object>();
859
860 return factory_->GetOrCreate(obj);
861 }
862
863 void WebAXObjectProxy::SetSelectedTextRange(int selection_start,
864 int length) {
865 accessibility_object().setSelectedTextRange(selection_start,
866 selection_start + length);
867 }
868
869 bool WebAXObjectProxy::IsAttributeSettable(const std::string& attribute) {
870 bool settable = false;
871 if (attribute == "AXValue")
872 settable = accessibility_object().canSetValueAttribute();
873 return settable;
874 }
875
876 bool WebAXObjectProxy::IsPressActionSupported() {
877 return accessibility_object().canPress();
878 }
879
880 bool WebAXObjectProxy::IsIncrementActionSupported() {
881 return accessibility_object().canIncrement();
882 }
883
884 bool WebAXObjectProxy::IsDecrementActionSupported() {
885 return accessibility_object().canDecrement();
886 }
887
888 v8::Handle<v8::Object> WebAXObjectProxy::ParentElement() {
889 blink::WebAXObject parent_object = accessibility_object().parentObject();
890 while (parent_object.accessibilityIsIgnored())
891 parent_object = parent_object.parentObject();
892 return factory_->GetOrCreate(parent_object);
893 }
894
895 void WebAXObjectProxy::Increment() {
896 accessibility_object().increment();
897 }
898
899 void WebAXObjectProxy::Decrement() {
900 accessibility_object().decrement();
901 }
902
903 void WebAXObjectProxy::ShowMenu() {
904 }
905
906 void WebAXObjectProxy::Press() {
907 accessibility_object().press();
908 }
909
910 bool WebAXObjectProxy::IsEqual(v8::Handle<v8::Object> proxy) {
911 WebAXObjectProxy* unwrapped_proxy = NULL;
912 if (!gin::ConvertFromV8(blink::mainThreadIsolate(), proxy, &unwrapped_proxy))
913 return false;
914 return unwrapped_proxy->IsEqualToObject(accessibility_object_);
915 }
916
917 void WebAXObjectProxy::AddNotificationListener(
918 v8::Handle<v8::Function> callback) {
919 v8::Isolate* isolate = blink::mainThreadIsolate();
920 notification_callbacks_.push_back(
921 UnsafePersistent<v8::Function>(isolate, callback));
922 }
923
924 void WebAXObjectProxy::RemoveNotificationListener() {
925 // FIXME: Implement this.
926 }
927
928 void WebAXObjectProxy::TakeFocus() {
929 accessibility_object().setFocused(true);
930 }
931
932 void WebAXObjectProxy::ScrollToMakeVisible() {
933 accessibility_object().scrollToMakeVisible();
934 }
935
936 void WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus(int x, int y,
937 int width, int height) {
938 accessibility_object().scrollToMakeVisibleWithSubFocus(
939 blink::WebRect(x, y, width, height));
940 }
941
942 void WebAXObjectProxy::ScrollToGlobalPoint(int x, int y) {
943 accessibility_object().scrollToGlobalPoint(blink::WebPoint(x, y));
944 }
945
946 int WebAXObjectProxy::WordStart(int character_index) {
947 if (accessibility_object().role() != blink::WebAXRoleStaticText)
948 return -1;
949
950 int word_start, word_end;
951 GetBoundariesForOneWord(accessibility_object(), character_index,
952 word_start, word_end);
953 return word_start;
954 }
955
956 int WebAXObjectProxy::WordEnd(int character_index) {
957 if (accessibility_object().role() != blink::WebAXRoleStaticText)
958 return -1;
959
960 int word_start, word_end;
961 GetBoundariesForOneWord(accessibility_object(), character_index,
962 word_start, word_end);
963 return word_end;
964 }
965
966 void WebAXObjectProxy::ClearNotificationCallbacks() {
967 for (CallbackList::iterator it = notification_callbacks_.begin();
968 it != notification_callbacks_.end(); ++it) {
969 it->Dispose();
970 }
971 notification_callbacks_.clear();
972 }
973
974 RootWebAXObjectProxy::RootWebAXObjectProxy(
975 const blink::WebAXObject &object, Factory *factory)
976 : WebAXObjectProxy(object, factory) {
977 }
978
979 v8::Handle<v8::Object> RootWebAXObjectProxy::GetChildAtIndex(unsigned index) {
980 if (index)
981 return v8::Handle<v8::Object>();
982
983 return factory()->GetOrCreate(accessibility_object());
984 }
985
986 bool RootWebAXObjectProxy::IsRoot() const {
987 return true;
988 }
989
990 WebAXObjectProxyList::WebAXObjectProxyList() {
991 }
992
993 WebAXObjectProxyList::~WebAXObjectProxyList() {
994 Clear();
995 }
996
997 void WebAXObjectProxyList::Clear() {
998 for (ElementList::iterator i = elements_.begin(); i != elements_.end(); ++i)
999 i->Dispose();
1000 elements_.clear();
1001 }
1002
1003 v8::Handle<v8::Object> WebAXObjectProxyList::GetOrCreate(
1004 const blink::WebAXObject& object) {
1005 if (object.isNull())
1006 return v8::Handle<v8::Object>();
1007
1008 v8::Isolate* isolate = blink::mainThreadIsolate();
1009
1010 size_t elementCount = elements_.size();
1011 for (size_t i = 0; i < elementCount; i++) {
1012 WebAXObjectProxy* unwrapped_object = NULL;
1013 bool result = gin::ConvertFromV8(isolate, elements_[i].NewLocal(isolate),
1014 &unwrapped_object);
1015 DCHECK(result);
1016 DCHECK(unwrapped_object);
1017 if (unwrapped_object->IsEqualToObject(object))
1018 return elements_[i].NewLocal(isolate);
1019 }
1020
1021 v8::Handle<v8::Object> handle = gin::CreateHandle(
1022 isolate, new WebAXObjectProxy(object, this)).ToV8()->ToObject();
1023 UnsafePersistent<v8::Object> unsafe_handle(isolate, handle);
1024 elements_.push_back(unsafe_handle);
1025 return unsafe_handle.NewLocal(isolate);
1026 }
1027
1028 v8::Handle<v8::Object> WebAXObjectProxyList::CreateRoot(
1029 const blink::WebAXObject& object) {
1030 v8::Isolate* isolate = blink::mainThreadIsolate();
1031 v8::Handle<v8::Object> handle = gin::CreateHandle(
1032 isolate, new RootWebAXObjectProxy(object, this)).ToV8()->ToObject();
1033 UnsafePersistent<v8::Object> unsafe_handle(isolate, handle);
1034 elements_.push_back(unsafe_handle);
1035 return unsafe_handle.NewLocal(isolate);
1036 }
1037
1038 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698