1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32 #include "public/web/WebAXObject.h"
33
34 #include "core/HTMLNames.h"
35 #include "core/accessibility/AXObject.h"
36 #include "core/accessibility/AXObjectCache.h"
37 #include "core/accessibility/AXTable.h"
38 #include "core/accessibility/AXTableCell.h"
39 #include "core/accessibility/AXTableColumn.h"
40 #include "core/accessibility/AXTableRow.h"
41 #include "core/css/CSSPrimitiveValueMappings.h"
42 #include "core/dom/Document.h"
43 #include "core/dom/Node.h"
44 #include "core/frame/FrameView.h"
45 #include "core/page/EventHandler.h"
46 #include "core/rendering/RenderView.h"
47 #include "core/rendering/style/RenderStyle.h"
48 #include "platform/PlatformKeyboardEvent.h"
49 #include "public/platform/WebPoint.h"
50 #include "public/platform/WebRect.h"
51 #include "public/platform/WebString.h"
52 #include "public/platform/WebURL.h"
53 #include "public/web/WebDocument.h"
54 #include "public/web/WebNode.h"
55 #include "wtf/text/StringBuilder.h"
56
57 namespace blink {
58
59 #if ENABLE(ASSERT)
60 // It's not safe to call some WebAXObject APIs if a layout is pending.
61 // Clients should call updateLayoutAndCheckValidity first.
isLayoutClean(Document * document)62 static bool isLayoutClean(Document* document)
63 {
64 if (!document || !document->view())
65 return false;
66 return document->lifecycle().state() >= DocumentLifecycle::LayoutClean
67 || (document->lifecycle().state() == DocumentLifecycle::StyleClean && !document->view()->needsLayout());
68 }
69 #endif
70
reset()71 void WebAXObject::reset()
72 {
73 m_private.reset();
74 }
75
assign(const WebAXObject & other)76 void WebAXObject::assign(const WebAXObject& other)
77 {
78 m_private = other.m_private;
79 }
80
equals(const WebAXObject & n) const81 bool WebAXObject::equals(const WebAXObject& n) const
82 {
83 return m_private.get() == n.m_private.get();
84 }
85
isDetached() const86 bool WebAXObject::isDetached() const
87 {
88 if (m_private.isNull())
89 return true;
90
91 return m_private->isDetached();
92 }
93
axID() const94 int WebAXObject::axID() const
95 {
96 if (isDetached())
97 return -1;
98
99 return m_private->axObjectID();
100 }
101
updateLayoutAndCheckValidity()102 bool WebAXObject::updateLayoutAndCheckValidity()
103 {
104 if (!isDetached()) {
105 Document* document = m_private->document();
106 if (!document || !document->topDocument().view())
107 return false;
108 document->topDocument().view()->updateLayoutAndStyleIfNeededRecursive();
109 }
110
111 // Doing a layout can cause this object to be invalid, so check again.
112 return !isDetached();
113 }
114
updateBackingStoreAndCheckValidity()115 bool WebAXObject::updateBackingStoreAndCheckValidity()
116 {
117 return updateLayoutAndCheckValidity();
118 }
119
accessibilityDescription() const120 WebString WebAXObject::accessibilityDescription() const
121 {
122 if (isDetached())
123 return WebString();
124
125 ASSERT(isLayoutClean(m_private->document()));
126
127 return m_private->accessibilityDescription();
128 }
129
actionVerb() const130 WebString WebAXObject::actionVerb() const
131 {
132 if (isDetached())
133 return WebString();
134
135 return m_private->actionVerb();
136 }
137
canDecrement() const138 bool WebAXObject::canDecrement() const
139 {
140 if (isDetached())
141 return false;
142
143 return m_private->isSlider();
144 }
145
canIncrement() const146 bool WebAXObject::canIncrement() const
147 {
148 if (isDetached())
149 return false;
150
151 return m_private->isSlider();
152 }
153
canPress() const154 bool WebAXObject::canPress() const
155 {
156 if (isDetached())
157 return false;
158
159 return m_private->actionElement() || m_private->isButton() || m_private->isMenuRelated();
160 }
161
canSetFocusAttribute() const162 bool WebAXObject::canSetFocusAttribute() const
163 {
164 if (isDetached())
165 return false;
166
167 return m_private->canSetFocusAttribute();
168 }
169
canSetValueAttribute() const170 bool WebAXObject::canSetValueAttribute() const
171 {
172 if (isDetached())
173 return false;
174
175 return m_private->canSetValueAttribute();
176 }
177
childCount() const178 unsigned WebAXObject::childCount() const
179 {
180 if (isDetached())
181 return 0;
182
183 return m_private->children().size();
184 }
185
childAt(unsigned index) const186 WebAXObject WebAXObject::childAt(unsigned index) const
187 {
188 if (isDetached())
189 return WebAXObject();
190
191 if (m_private->children().size() <= index)
192 return WebAXObject();
193
194 return WebAXObject(m_private->children()[index]);
195 }
196
parentObject() const197 WebAXObject WebAXObject::parentObject() const
198 {
199 if (isDetached())
200 return WebAXObject();
201
202 return WebAXObject(m_private->parentObject());
203 }
204
canSetSelectedAttribute() const205 bool WebAXObject::canSetSelectedAttribute() const
206 {
207 if (isDetached())
208 return 0;
209
210 return m_private->canSetSelectedAttribute();
211 }
212
isAnchor() const213 bool WebAXObject::isAnchor() const
214 {
215 if (isDetached())
216 return 0;
217
218 return m_private->isAnchor();
219 }
220
isAriaReadOnly() const221 bool WebAXObject::isAriaReadOnly() const
222 {
223 if (isDetached())
224 return 0;
225
226 return equalIgnoringCase(m_private->getAttribute(HTMLNames::aria_readonlyAttr), "true");
227 }
228
isButtonStateMixed() const229 bool WebAXObject::isButtonStateMixed() const
230 {
231 if (isDetached())
232 return 0;
233
234 return m_private->checkboxOrRadioValue() == ButtonStateMixed;
235 }
236
isChecked() const237 bool WebAXObject::isChecked() const
238 {
239 if (isDetached())
240 return 0;
241
242 return m_private->isChecked();
243 }
244
isClickable() const245 bool WebAXObject::isClickable() const
246 {
247 if (isDetached())
248 return 0;
249
250 return m_private->isClickable();
251 }
252
isCollapsed() const253 bool WebAXObject::isCollapsed() const
254 {
255 if (isDetached())
256 return 0;
257
258 return m_private->isCollapsed();
259 }
260
isControl() const261 bool WebAXObject::isControl() const
262 {
263 if (isDetached())
264 return 0;
265
266 return m_private->isControl();
267 }
268
isEnabled() const269 bool WebAXObject::isEnabled() const
270 {
271 if (isDetached())
272 return 0;
273
274 return m_private->isEnabled();
275 }
276
isFocused() const277 bool WebAXObject::isFocused() const
278 {
279 if (isDetached())
280 return 0;
281
282 return m_private->isFocused();
283 }
284
isHovered() const285 bool WebAXObject::isHovered() const
286 {
287 if (isDetached())
288 return 0;
289
290 return m_private->isHovered();
291 }
292
isIndeterminate() const293 bool WebAXObject::isIndeterminate() const
294 {
295 if (isDetached())
296 return 0;
297
298 return m_private->isIndeterminate();
299 }
300
isLinked() const301 bool WebAXObject::isLinked() const
302 {
303 if (isDetached())
304 return 0;
305
306 return m_private->isLinked();
307 }
308
isLoaded() const309 bool WebAXObject::isLoaded() const
310 {
311 if (isDetached())
312 return 0;
313
314 return m_private->isLoaded();
315 }
316
isMultiSelectable() const317 bool WebAXObject::isMultiSelectable() const
318 {
319 if (isDetached())
320 return 0;
321
322 return m_private->isMultiSelectable();
323 }
324
isOffScreen() const325 bool WebAXObject::isOffScreen() const
326 {
327 if (isDetached())
328 return 0;
329
330 return m_private->isOffScreen();
331 }
332
isPasswordField() const333 bool WebAXObject::isPasswordField() const
334 {
335 if (isDetached())
336 return 0;
337
338 return m_private->isPasswordField();
339 }
340
isPressed() const341 bool WebAXObject::isPressed() const
342 {
343 if (isDetached())
344 return 0;
345
346 return m_private->isPressed();
347 }
348
isReadOnly() const349 bool WebAXObject::isReadOnly() const
350 {
351 if (isDetached())
352 return 0;
353
354 return m_private->isReadOnly();
355 }
356
isRequired() const357 bool WebAXObject::isRequired() const
358 {
359 if (isDetached())
360 return 0;
361
362 return m_private->isRequired();
363 }
364
isSelected() const365 bool WebAXObject::isSelected() const
366 {
367 if (isDetached())
368 return 0;
369
370 return m_private->isSelected();
371 }
372
isSelectedOptionActive() const373 bool WebAXObject::isSelectedOptionActive() const
374 {
375 if (isDetached())
376 return false;
377
378 return m_private->isSelectedOptionActive();
379 }
380
isVertical() const381 bool WebAXObject::isVertical() const
382 {
383 if (isDetached())
384 return 0;
385
386 return m_private->orientation() == AccessibilityOrientationVertical;
387 }
388
isVisible() const389 bool WebAXObject::isVisible() const
390 {
391 if (isDetached())
392 return 0;
393
394 return m_private->isVisible();
395 }
396
isVisited() const397 bool WebAXObject::isVisited() const
398 {
399 if (isDetached())
400 return 0;
401
402 return m_private->isVisited();
403 }
404
accessKey() const405 WebString WebAXObject::accessKey() const
406 {
407 if (isDetached())
408 return WebString();
409
410 return WebString(m_private->accessKey());
411 }
412
ariaActiveDescendant() const413 WebAXObject WebAXObject::ariaActiveDescendant() const
414 {
415 if (isDetached())
416 return WebAXObject();
417
418 return WebAXObject(m_private->activeDescendant());
419 }
420
ariaControls(WebVector<WebAXObject> & controlsElements) const421 bool WebAXObject::ariaControls(WebVector<WebAXObject>& controlsElements) const
422 {
423 if (isDetached())
424 return false;
425
426 AXObject::AccessibilityChildrenVector controls;
427 m_private->ariaControlsElements(controls);
428
429 WebVector<WebAXObject> result(controls.size());
430 for (size_t i = 0; i < controls.size(); i++)
431 result[i] = WebAXObject(controls[i]);
432 controlsElements.swap(result);
433
434 return true;
435 }
436
ariaDescribedby(WebVector<WebAXObject> & describedbyElements) const437 bool WebAXObject::ariaDescribedby(WebVector<WebAXObject>& describedbyElements) const
438 {
439 if (isDetached())
440 return false;
441
442 AXObject::AccessibilityChildrenVector describedby;
443 m_private->ariaDescribedbyElements(describedby);
444
445 WebVector<WebAXObject> result(describedby.size());
446 for (size_t i = 0; i < describedby.size(); i++)
447 result[i] = WebAXObject(describedby[i]);
448 describedbyElements.swap(result);
449
450 return true;
451 }
452
ariaHasPopup() const453 bool WebAXObject::ariaHasPopup() const
454 {
455 if (isDetached())
456 return 0;
457
458 return m_private->ariaHasPopup();
459 }
460
ariaFlowTo(WebVector<WebAXObject> & flowToElements) const461 bool WebAXObject::ariaFlowTo(WebVector<WebAXObject>& flowToElements) const
462 {
463 if (isDetached())
464 return false;
465
466 AXObject::AccessibilityChildrenVector flowTo;
467 m_private->ariaFlowToElements(flowTo);
468
469 WebVector<WebAXObject> result(flowTo.size());
470 for (size_t i = 0; i < flowTo.size(); i++)
471 result[i] = WebAXObject(flowTo[i]);
472 flowToElements.swap(result);
473
474 return true;
475 }
476
ariaLabelledby(WebVector<WebAXObject> & labelledbyElements) const477 bool WebAXObject::ariaLabelledby(WebVector<WebAXObject>& labelledbyElements) const
478 {
479 if (isDetached())
480 return false;
481
482 AXObject::AccessibilityChildrenVector labelledby;
483 m_private->ariaLabelledbyElements(labelledby);
484
485 WebVector<WebAXObject> result(labelledby.size());
486 for (size_t i = 0; i < labelledby.size(); i++)
487 result[i] = WebAXObject(labelledby[i]);
488 labelledbyElements.swap(result);
489
490 return true;
491 }
492
ariaLiveRegionAtomic() const493 bool WebAXObject::ariaLiveRegionAtomic() const
494 {
495 if (isDetached())
496 return 0;
497
498 return m_private->ariaLiveRegionAtomic();
499 }
500
ariaLiveRegionBusy() const501 bool WebAXObject::ariaLiveRegionBusy() const
502 {
503 if (isDetached())
504 return 0;
505
506 return m_private->ariaLiveRegionBusy();
507 }
508
ariaLiveRegionRelevant() const509 WebString WebAXObject::ariaLiveRegionRelevant() const
510 {
511 if (isDetached())
512 return WebString();
513
514 return m_private->ariaLiveRegionRelevant();
515 }
516
ariaLiveRegionStatus() const517 WebString WebAXObject::ariaLiveRegionStatus() const
518 {
519 if (isDetached())
520 return WebString();
521
522 return m_private->ariaLiveRegionStatus();
523 }
524
ariaOwns(WebVector<WebAXObject> & ownsElements) const525 bool WebAXObject::ariaOwns(WebVector<WebAXObject>& ownsElements) const
526 {
527 if (isDetached())
528 return false;
529
530 AXObject::AccessibilityChildrenVector owns;
531 m_private->ariaOwnsElements(owns);
532
533 WebVector<WebAXObject> result(owns.size());
534 for (size_t i = 0; i < owns.size(); i++)
535 result[i] = WebAXObject(owns[i]);
536 ownsElements.swap(result);
537
538 return true;
539 }
540
boundingBoxRect() const541 WebRect WebAXObject::boundingBoxRect() const
542 {
543 if (isDetached())
544 return WebRect();
545
546 ASSERT(isLayoutClean(m_private->document()));
547
548 return pixelSnappedIntRect(m_private->elementRect());
549 }
550
canvasHasFallbackContent() const551 bool WebAXObject::canvasHasFallbackContent() const
552 {
553 if (isDetached())
554 return false;
555
556 return m_private->canvasHasFallbackContent();
557 }
558
clickPoint() const559 WebPoint WebAXObject::clickPoint() const
560 {
561 if (isDetached())
562 return WebPoint();
563
564 return WebPoint(m_private->clickPoint());
565 }
566
colorValue(int & r,int & g,int & b) const567 void WebAXObject::colorValue(int& r, int& g, int& b) const
568 {
569 if (isDetached())
570 return;
571
572 m_private->colorValue(r, g, b);
573 }
574
estimatedLoadingProgress() const575 double WebAXObject::estimatedLoadingProgress() const
576 {
577 if (isDetached())
578 return 0.0;
579
580 return m_private->estimatedLoadingProgress();
581 }
582
helpText() const583 WebString WebAXObject::helpText() const
584 {
585 if (isDetached())
586 return WebString();
587
588 return m_private->helpText();
589 }
590
headingLevel() const591 int WebAXObject::headingLevel() const
592 {
593 if (isDetached())
594 return 0;
595
596 return m_private->headingLevel();
597 }
598
hierarchicalLevel() const599 int WebAXObject::hierarchicalLevel() const
600 {
601 if (isDetached())
602 return 0;
603
604 return m_private->hierarchicalLevel();
605 }
606
hitTest(const WebPoint & point) const607 WebAXObject WebAXObject::hitTest(const WebPoint& point) const
608 {
609 if (isDetached())
610 return WebAXObject();
611
612 IntPoint contentsPoint = m_private->documentFrameView()->windowToContents(point);
613 RefPtr<AXObject> hit = m_private->accessibilityHitTest(contentsPoint);
614
615 if (hit)
616 return WebAXObject(hit);
617
618 if (m_private->elementRect().contains(contentsPoint))
619 return *this;
620
621 return WebAXObject();
622 }
623
keyboardShortcut() const624 WebString WebAXObject::keyboardShortcut() const
625 {
626 if (isDetached())
627 return WebString();
628
629 String accessKey = m_private->accessKey();
630 if (accessKey.isNull())
631 return WebString();
632
633 DEFINE_STATIC_LOCAL(String, modifierString, ());
634 if (modifierString.isNull()) {
635 unsigned modifiers = EventHandler::accessKeyModifiers();
636 // Follow the same order as Mozilla MSAA implementation:
637 // Ctrl+Alt+Shift+Meta+key. MSDN states that keyboard shortcut strings
638 // should not be localized and defines the separator as "+".
639 StringBuilder modifierStringBuilder;
640 if (modifiers & PlatformEvent::CtrlKey)
641 modifierStringBuilder.appendLiteral("Ctrl+");
642 if (modifiers & PlatformEvent::AltKey)
643 modifierStringBuilder.appendLiteral("Alt+");
644 if (modifiers & PlatformEvent::ShiftKey)
645 modifierStringBuilder.appendLiteral("Shift+");
646 if (modifiers & PlatformEvent::MetaKey)
647 modifierStringBuilder.appendLiteral("Win+");
648 modifierString = modifierStringBuilder.toString();
649 }
650
651 return String(modifierString + accessKey);
652 }
653
performDefaultAction() const654 bool WebAXObject::performDefaultAction() const
655 {
656 if (isDetached())
657 return false;
658
659 return m_private->performDefaultAction();
660 }
661
increment() const662 bool WebAXObject::increment() const
663 {
664 if (isDetached())
665 return false;
666
667 if (canIncrement()) {
668 m_private->increment();
669 return true;
670 }
671 return false;
672 }
673
decrement() const674 bool WebAXObject::decrement() const
675 {
676 if (isDetached())
677 return false;
678
679 if (canDecrement()) {
680 m_private->decrement();
681 return true;
682 }
683 return false;
684 }
685
press() const686 bool WebAXObject::press() const
687 {
688 if (isDetached())
689 return false;
690
691 return m_private->press();
692 }
693
role() const694 WebAXRole WebAXObject::role() const
695 {
696 if (isDetached())
697 return WebAXRoleUnknown;
698
699 return static_cast<WebAXRole>(m_private->roleValue());
700 }
701
selectionEnd() const702 unsigned WebAXObject::selectionEnd() const
703 {
704 if (isDetached())
705 return 0;
706
707 return m_private->selectedTextRange().start + m_private->selectedTextRange().length;
708 }
709
selectionStart() const710 unsigned WebAXObject::selectionStart() const
711 {
712 if (isDetached())
713 return 0;
714
715 return m_private->selectedTextRange().start;
716 }
717
selectionEndLineNumber() const718 unsigned WebAXObject::selectionEndLineNumber() const
719 {
720 if (isDetached())
721 return 0;
722
723 VisiblePosition position = m_private->visiblePositionForIndex(selectionEnd());
724 int lineNumber = m_private->lineForPosition(position);
725 if (lineNumber < 0)
726 return 0;
727 return lineNumber;
728 }
729
selectionStartLineNumber() const730 unsigned WebAXObject::selectionStartLineNumber() const
731 {
732 if (isDetached())
733 return 0;
734
735 VisiblePosition position = m_private->visiblePositionForIndex(selectionStart());
736 int lineNumber = m_private->lineForPosition(position);
737 if (lineNumber < 0)
738 return 0;
739 return lineNumber;
740 }
741
setFocused(bool on) const742 void WebAXObject::setFocused(bool on) const
743 {
744 if (!isDetached())
745 m_private->setFocused(on);
746 }
747
setSelectedTextRange(int selectionStart,int selectionEnd) const748 void WebAXObject::setSelectedTextRange(int selectionStart, int selectionEnd) const
749 {
750 if (isDetached())
751 return;
752
753 m_private->setSelectedTextRange(AXObject::PlainTextRange(selectionStart, selectionEnd - selectionStart));
754 }
755
stringValue() const756 WebString WebAXObject::stringValue() const
757 {
758 if (isDetached())
759 return WebString();
760
761 return m_private->stringValue();
762 }
763
title() const764 WebString WebAXObject::title() const
765 {
766 if (isDetached())
767 return WebString();
768
769 ASSERT(isLayoutClean(m_private->document()));
770
771 return m_private->title();
772 }
773
titleUIElement() const774 WebAXObject WebAXObject::titleUIElement() const
775 {
776 if (isDetached())
777 return WebAXObject();
778
779 if (!m_private->exposesTitleUIElement())
780 return WebAXObject();
781
782 return WebAXObject(m_private->titleUIElement());
783 }
784
url() const785 WebURL WebAXObject::url() const
786 {
787 if (isDetached())
788 return WebURL();
789
790 return m_private->url();
791 }
792
supportsRangeValue() const793 bool WebAXObject::supportsRangeValue() const
794 {
795 if (isDetached())
796 return false;
797
798 return m_private->supportsRangeValue();
799 }
800
valueDescription() const801 WebString WebAXObject::valueDescription() const
802 {
803 if (isDetached())
804 return WebString();
805
806 return m_private->valueDescription();
807 }
808
valueForRange() const809 float WebAXObject::valueForRange() const
810 {
811 if (isDetached())
812 return 0.0;
813
814 return m_private->valueForRange();
815 }
816
maxValueForRange() const817 float WebAXObject::maxValueForRange() const
818 {
819 if (isDetached())
820 return 0.0;
821
822 return m_private->maxValueForRange();
823 }
824
minValueForRange() const825 float WebAXObject::minValueForRange() const
826 {
827 if (isDetached())
828 return 0.0;
829
830 return m_private->minValueForRange();
831 }
832
node() const833 WebNode WebAXObject::node() const
834 {
835 if (isDetached())
836 return WebNode();
837
838 Node* node = m_private->node();
839 if (!node)
840 return WebNode();
841
842 return WebNode(node);
843 }
844
document() const845 WebDocument WebAXObject::document() const
846 {
847 if (isDetached())
848 return WebDocument();
849
850 Document* document = m_private->document();
851 if (!document)
852 return WebDocument();
853
854 return WebDocument(document);
855 }
856
hasComputedStyle() const857 bool WebAXObject::hasComputedStyle() const
858 {
859 if (isDetached())
860 return false;
861
862 Document* document = m_private->document();
863 if (document)
864 document->updateRenderTreeIfNeeded();
865
866 Node* node = m_private->node();
867 if (!node)
868 return false;
869
870 return node->computedStyle();
871 }
872
computedStyleDisplay() const873 WebString WebAXObject::computedStyleDisplay() const
874 {
875 if (isDetached())
876 return WebString();
877
878 Document* document = m_private->document();
879 if (document)
880 document->updateRenderTreeIfNeeded();
881
882 Node* node = m_private->node();
883 if (!node)
884 return WebString();
885
886 RenderStyle* renderStyle = node->computedStyle();
887 if (!renderStyle)
888 return WebString();
889
890 return WebString(CSSPrimitiveValue::create(renderStyle->display())->getStringValue());
891 }
892
accessibilityIsIgnored() const893 bool WebAXObject::accessibilityIsIgnored() const
894 {
895 if (isDetached())
896 return false;
897
898 return m_private->accessibilityIsIgnored();
899 }
900
lineBreaks(WebVector<int> & result) const901 bool WebAXObject::lineBreaks(WebVector<int>& result) const
902 {
903 if (isDetached())
904 return false;
905
906 Vector<int> lineBreaksVector;
907 m_private->lineBreaks(lineBreaksVector);
908
909 size_t vectorSize = lineBreaksVector.size();
910 WebVector<int> lineBreaksWebVector(vectorSize);
911 for (size_t i = 0; i< vectorSize; i++)
912 lineBreaksWebVector[i] = lineBreaksVector[i];
913 result.swap(lineBreaksWebVector);
914
915 return true;
916 }
917
columnCount() const918 unsigned WebAXObject::columnCount() const
919 {
920 if (isDetached())
921 return false;
922
923 if (!m_private->isAXTable())
924 return 0;
925
926 return toAXTable(m_private.get())->columnCount();
927 }
928
rowCount() const929 unsigned WebAXObject::rowCount() const
930 {
931 if (isDetached())
932 return false;
933
934 if (!m_private->isAXTable())
935 return 0;
936
937 return toAXTable(m_private.get())->rowCount();
938 }
939
cellForColumnAndRow(unsigned column,unsigned row) const940 WebAXObject WebAXObject::cellForColumnAndRow(unsigned column, unsigned row) const
941 {
942 if (isDetached())
943 return WebAXObject();
944
945 if (!m_private->isAXTable())
946 return WebAXObject();
947
948 AXTableCell* cell = toAXTable(m_private.get())->cellForColumnAndRow(column, row);
949 return WebAXObject(static_cast<AXObject*>(cell));
950 }
951
headerContainerObject() const952 WebAXObject WebAXObject::headerContainerObject() const
953 {
954 if (isDetached())
955 return WebAXObject();
956
957 if (!m_private->isAXTable())
958 return WebAXObject();
959
960 return WebAXObject(toAXTable(m_private.get())->headerContainer());
961 }
962
rowAtIndex(unsigned rowIndex) const963 WebAXObject WebAXObject::rowAtIndex(unsigned rowIndex) const
964 {
965 if (isDetached())
966 return WebAXObject();
967
968 if (!m_private->isAXTable())
969 return WebAXObject();
970
971 const AXObject::AccessibilityChildrenVector& rows = toAXTable(m_private.get())->rows();
972 if (rowIndex < rows.size())
973 return WebAXObject(rows[rowIndex]);
974
975 return WebAXObject();
976 }
977
columnAtIndex(unsigned columnIndex) const978 WebAXObject WebAXObject::columnAtIndex(unsigned columnIndex) const
979 {
980 if (isDetached())
981 return WebAXObject();
982
983 if (!m_private->isAXTable())
984 return WebAXObject();
985
986 const AXObject::AccessibilityChildrenVector& columns = toAXTable(m_private.get())->columns();
987 if (columnIndex < columns.size())
988 return WebAXObject(columns[columnIndex]);
989
990 return WebAXObject();
991 }
992
rowIndex() const993 unsigned WebAXObject::rowIndex() const
994 {
995 if (isDetached())
996 return 0;
997
998 if (!m_private->isTableRow())
999 return 0;
1000
1001 return toAXTableRow(m_private.get())->rowIndex();
1002 }
1003
rowHeader() const1004 WebAXObject WebAXObject::rowHeader() const
1005 {
1006 if (isDetached())
1007 return WebAXObject();
1008
1009 if (!m_private->isTableRow())
1010 return WebAXObject();
1011
1012 return WebAXObject(toAXTableRow(m_private.get())->headerObject());
1013 }
1014
columnIndex() const1015 unsigned WebAXObject::columnIndex() const
1016 {
1017 if (isDetached())
1018 return 0;
1019
1020 if (m_private->roleValue() != ColumnRole)
1021 return 0;
1022
1023 return toAXTableColumn(m_private.get())->columnIndex();
1024 }
1025
columnHeader() const1026 WebAXObject WebAXObject::columnHeader() const
1027 {
1028 if (isDetached())
1029 return WebAXObject();
1030
1031 if (m_private->roleValue() != ColumnRole)
1032 return WebAXObject();
1033
1034 return WebAXObject(toAXTableColumn(m_private.get())->headerObject());
1035 }
1036
cellColumnIndex() const1037 unsigned WebAXObject::cellColumnIndex() const
1038 {
1039 if (isDetached())
1040 return 0;
1041
1042 if (!m_private->isTableCell())
1043 return 0;
1044
1045 pair<unsigned, unsigned> columnRange;
1046 toAXTableCell(m_private.get())->columnIndexRange(columnRange);
1047 return columnRange.first;
1048 }
1049
cellColumnSpan() const1050 unsigned WebAXObject::cellColumnSpan() const
1051 {
1052 if (isDetached())
1053 return 0;
1054
1055 if (!m_private->isTableCell())
1056 return 0;
1057
1058 pair<unsigned, unsigned> columnRange;
1059 toAXTableCell(m_private.get())->columnIndexRange(columnRange);
1060 return columnRange.second;
1061 }
1062
cellRowIndex() const1063 unsigned WebAXObject::cellRowIndex() const
1064 {
1065 if (isDetached())
1066 return 0;
1067
1068 if (!m_private->isTableCell())
1069 return 0;
1070
1071 pair<unsigned, unsigned> rowRange;
1072 toAXTableCell(m_private.get())->rowIndexRange(rowRange);
1073 return rowRange.first;
1074 }
1075
cellRowSpan() const1076 unsigned WebAXObject::cellRowSpan() const
1077 {
1078 if (isDetached())
1079 return 0;
1080
1081 if (!m_private->isTableCell())
1082 return 0;
1083
1084 pair<unsigned, unsigned> rowRange;
1085 toAXTableCell(m_private.get())->rowIndexRange(rowRange);
1086 return rowRange.second;
1087 }
1088
textDirection() const1089 WebAXTextDirection WebAXObject::textDirection() const
1090 {
1091 if (isDetached())
1092 return WebAXTextDirectionLR;
1093
1094 return static_cast<WebAXTextDirection>(m_private->textDirection());
1095 }
1096
characterOffsets(WebVector<int> & offsets) const1097 void WebAXObject::characterOffsets(WebVector<int>& offsets) const
1098 {
1099 if (isDetached())
1100 return;
1101
1102 Vector<int> offsetsVector;
1103 m_private->textCharacterOffsets(offsetsVector);
1104
1105 size_t vectorSize = offsetsVector.size();
1106 WebVector<int> offsetsWebVector(vectorSize);
1107 for (size_t i = 0; i < vectorSize; i++)
1108 offsetsWebVector[i] = offsetsVector[i];
1109 offsets.swap(offsetsWebVector);
1110 }
1111
wordBoundaries(WebVector<int> & starts,WebVector<int> & ends) const1112 void WebAXObject::wordBoundaries(WebVector<int>& starts, WebVector<int>& ends) const
1113 {
1114 if (isDetached())
1115 return;
1116
1117 Vector<AXObject::PlainTextRange> words;
1118 m_private->wordBoundaries(words);
1119
1120 WebVector<int> startsWebVector(words.size());
1121 WebVector<int> endsWebVector(words.size());
1122 for (size_t i = 0; i < words.size(); i++) {
1123 startsWebVector[i] = words[i].start;
1124 endsWebVector[i] = words[i].start + words[i].length;
1125 }
1126 starts.swap(startsWebVector);
1127 ends.swap(endsWebVector);
1128 }
1129
scrollToMakeVisible() const1130 void WebAXObject::scrollToMakeVisible() const
1131 {
1132 if (!isDetached())
1133 m_private->scrollToMakeVisible();
1134 }
1135
scrollToMakeVisibleWithSubFocus(const WebRect & subfocus) const1136 void WebAXObject::scrollToMakeVisibleWithSubFocus(const WebRect& subfocus) const
1137 {
1138 if (!isDetached())
1139 m_private->scrollToMakeVisibleWithSubFocus(subfocus);
1140 }
1141
scrollToGlobalPoint(const WebPoint & point) const1142 void WebAXObject::scrollToGlobalPoint(const WebPoint& point) const
1143 {
1144 if (!isDetached())
1145 m_private->scrollToGlobalPoint(point);
1146 }
1147
WebAXObject(const WTF::PassRefPtr<AXObject> & object)1148 WebAXObject::WebAXObject(const WTF::PassRefPtr<AXObject>& object)
1149 : m_private(object)
1150 {
1151 }
1152
operator =(const WTF::PassRefPtr<AXObject> & object)1153 WebAXObject& WebAXObject::operator=(const WTF::PassRefPtr<AXObject>& object)
1154 {
1155 m_private = object;
1156 return *this;
1157 }
1158
operator WTF::PassRefPtr<AXObject>() const1159 WebAXObject::operator WTF::PassRefPtr<AXObject>() const
1160 {
1161 return m_private.get();
1162 }
1163
1164 } // namespace blink
1165