• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 using namespace WebCore;
58 
59 namespace blink {
60 
reset()61 void WebAXObject::reset()
62 {
63     m_private.reset();
64 }
65 
assign(const blink::WebAXObject & other)66 void WebAXObject::assign(const blink::WebAXObject& other)
67 {
68     m_private = other.m_private;
69 }
70 
equals(const WebAXObject & n) const71 bool WebAXObject::equals(const WebAXObject& n) const
72 {
73     return m_private.get() == n.m_private.get();
74 }
75 
76 // static
enableAccessibility()77 void WebAXObject::enableAccessibility()
78 {
79     AXObjectCache::enableAccessibility();
80 }
81 
82 // static
accessibilityEnabled()83 bool WebAXObject::accessibilityEnabled()
84 {
85     return AXObjectCache::accessibilityEnabled();
86 }
87 
88 // static
enableInlineTextBoxAccessibility()89 void WebAXObject::enableInlineTextBoxAccessibility()
90 {
91     AXObjectCache::setInlineTextBoxAccessibility(true);
92 }
93 
isDetached() const94 bool WebAXObject::isDetached() const
95 {
96     if (m_private.isNull())
97         return true;
98 
99     return m_private->isDetached();
100 }
101 
axID() const102 int WebAXObject::axID() const
103 {
104     if (isDetached())
105         return -1;
106 
107     return m_private->axObjectID();
108 }
109 
updateLayoutAndCheckValidity()110 bool WebAXObject::updateLayoutAndCheckValidity()
111 {
112     if (!isDetached()) {
113         Document* document = m_private->document();
114         if (!document || !document->topDocument().view())
115             return false;
116         document->topDocument().view()->updateLayoutAndStyleIfNeededRecursive();
117     }
118 
119     // Doing a layout can cause this object to be invalid, so check again.
120     return !isDetached();
121 }
122 
updateBackingStoreAndCheckValidity()123 bool WebAXObject::updateBackingStoreAndCheckValidity()
124 {
125     return updateLayoutAndCheckValidity();
126 }
127 
accessibilityDescription() const128 WebString WebAXObject::accessibilityDescription() const
129 {
130     if (isDetached())
131         return WebString();
132 
133     return m_private->accessibilityDescription();
134 }
135 
actionVerb() const136 WebString WebAXObject::actionVerb() const
137 {
138     if (isDetached())
139         return WebString();
140 
141     return m_private->actionVerb();
142 }
143 
canDecrement() const144 bool WebAXObject::canDecrement() const
145 {
146     if (isDetached())
147         return false;
148 
149     return m_private->isSlider();
150 }
151 
canIncrement() const152 bool WebAXObject::canIncrement() const
153 {
154     if (isDetached())
155         return false;
156 
157     return m_private->isSlider();
158 }
159 
canPress() const160 bool WebAXObject::canPress() const
161 {
162     if (isDetached())
163         return false;
164 
165     return m_private->actionElement() || m_private->isButton() || m_private->isMenuRelated();
166 }
167 
canSetFocusAttribute() const168 bool WebAXObject::canSetFocusAttribute() const
169 {
170     if (isDetached())
171         return false;
172 
173     return m_private->canSetFocusAttribute();
174 }
175 
canSetValueAttribute() const176 bool WebAXObject::canSetValueAttribute() const
177 {
178     if (isDetached())
179         return false;
180 
181     return m_private->canSetValueAttribute();
182 }
183 
childCount() const184 unsigned WebAXObject::childCount() const
185 {
186     if (isDetached())
187         return 0;
188 
189     return m_private->children().size();
190 }
191 
childAt(unsigned index) const192 WebAXObject WebAXObject::childAt(unsigned index) const
193 {
194     if (isDetached())
195         return WebAXObject();
196 
197     if (m_private->children().size() <= index)
198         return WebAXObject();
199 
200     return WebAXObject(m_private->children()[index]);
201 }
202 
parentObject() const203 WebAXObject WebAXObject::parentObject() const
204 {
205     if (isDetached())
206         return WebAXObject();
207 
208     return WebAXObject(m_private->parentObject());
209 }
210 
canSetSelectedAttribute() const211 bool WebAXObject::canSetSelectedAttribute() const
212 {
213     if (isDetached())
214         return 0;
215 
216     return m_private->canSetSelectedAttribute();
217 }
218 
isAnchor() const219 bool WebAXObject::isAnchor() const
220 {
221     if (isDetached())
222         return 0;
223 
224     return m_private->isAnchor();
225 }
226 
isAriaReadOnly() const227 bool WebAXObject::isAriaReadOnly() const
228 {
229     if (isDetached())
230         return 0;
231 
232     return equalIgnoringCase(m_private->getAttribute(HTMLNames::aria_readonlyAttr), "true");
233 }
234 
isButtonStateMixed() const235 bool WebAXObject::isButtonStateMixed() const
236 {
237     if (isDetached())
238         return 0;
239 
240     return m_private->checkboxOrRadioValue() == ButtonStateMixed;
241 }
242 
isChecked() const243 bool WebAXObject::isChecked() const
244 {
245     if (isDetached())
246         return 0;
247 
248     return m_private->isChecked();
249 }
250 
isClickable() const251 bool WebAXObject::isClickable() const
252 {
253     if (isDetached())
254         return 0;
255 
256     return m_private->isClickable();
257 }
258 
isCollapsed() const259 bool WebAXObject::isCollapsed() const
260 {
261     if (isDetached())
262         return 0;
263 
264     return m_private->isCollapsed();
265 }
266 
isControl() const267 bool WebAXObject::isControl() const
268 {
269     if (isDetached())
270         return 0;
271 
272     return m_private->isControl();
273 }
274 
isEnabled() const275 bool WebAXObject::isEnabled() const
276 {
277     if (isDetached())
278         return 0;
279 
280     return m_private->isEnabled();
281 }
282 
isFocused() const283 bool WebAXObject::isFocused() const
284 {
285     if (isDetached())
286         return 0;
287 
288     return m_private->isFocused();
289 }
290 
isHovered() const291 bool WebAXObject::isHovered() const
292 {
293     if (isDetached())
294         return 0;
295 
296     return m_private->isHovered();
297 }
298 
isIndeterminate() const299 bool WebAXObject::isIndeterminate() const
300 {
301     if (isDetached())
302         return 0;
303 
304     return m_private->isIndeterminate();
305 }
306 
isLinked() const307 bool WebAXObject::isLinked() const
308 {
309     if (isDetached())
310         return 0;
311 
312     return m_private->isLinked();
313 }
314 
isLoaded() const315 bool WebAXObject::isLoaded() const
316 {
317     if (isDetached())
318         return 0;
319 
320     return m_private->isLoaded();
321 }
322 
isMultiSelectable() const323 bool WebAXObject::isMultiSelectable() const
324 {
325     if (isDetached())
326         return 0;
327 
328     return m_private->isMultiSelectable();
329 }
330 
isOffScreen() const331 bool WebAXObject::isOffScreen() const
332 {
333     if (isDetached())
334         return 0;
335 
336     return m_private->isOffScreen();
337 }
338 
isPasswordField() const339 bool WebAXObject::isPasswordField() const
340 {
341     if (isDetached())
342         return 0;
343 
344     return m_private->isPasswordField();
345 }
346 
isPressed() const347 bool WebAXObject::isPressed() const
348 {
349     if (isDetached())
350         return 0;
351 
352     return m_private->isPressed();
353 }
354 
isReadOnly() const355 bool WebAXObject::isReadOnly() const
356 {
357     if (isDetached())
358         return 0;
359 
360     return m_private->isReadOnly();
361 }
362 
isRequired() const363 bool WebAXObject::isRequired() const
364 {
365     if (isDetached())
366         return 0;
367 
368     return m_private->isRequired();
369 }
370 
isSelected() const371 bool WebAXObject::isSelected() const
372 {
373     if (isDetached())
374         return 0;
375 
376     return m_private->isSelected();
377 }
378 
isSelectedOptionActive() const379 bool WebAXObject::isSelectedOptionActive() const
380 {
381     if (isDetached())
382         return false;
383 
384     return m_private->isSelectedOptionActive();
385 }
386 
isVertical() const387 bool WebAXObject::isVertical() const
388 {
389     if (isDetached())
390         return 0;
391 
392     return m_private->orientation() == AccessibilityOrientationVertical;
393 }
394 
isVisible() const395 bool WebAXObject::isVisible() const
396 {
397     if (isDetached())
398         return 0;
399 
400     return m_private->isVisible();
401 }
402 
isVisited() const403 bool WebAXObject::isVisited() const
404 {
405     if (isDetached())
406         return 0;
407 
408     return m_private->isVisited();
409 }
410 
accessKey() const411 WebString WebAXObject::accessKey() const
412 {
413     if (isDetached())
414         return WebString();
415 
416     return WebString(m_private->accessKey());
417 }
418 
ariaActiveDescendant() const419 WebAXObject WebAXObject::ariaActiveDescendant() const
420 {
421     if (isDetached())
422         return WebAXObject();
423 
424     return WebAXObject(m_private->activeDescendant());
425 }
426 
ariaControls(WebVector<WebAXObject> & controlsElements) const427 bool WebAXObject::ariaControls(WebVector<WebAXObject>& controlsElements) const
428 {
429     if (isDetached())
430         return false;
431 
432     AXObject::AccessibilityChildrenVector controls;
433     m_private->ariaControlsElements(controls);
434 
435     WebVector<WebAXObject> result(controls.size());
436     for (size_t i = 0; i < controls.size(); i++)
437         result[i] = WebAXObject(controls[i]);
438     controlsElements.swap(result);
439 
440     return true;
441 }
442 
ariaDescribedby(WebVector<WebAXObject> & describedbyElements) const443 bool WebAXObject::ariaDescribedby(WebVector<WebAXObject>& describedbyElements) const
444 {
445     if (isDetached())
446         return false;
447 
448     AXObject::AccessibilityChildrenVector describedby;
449     m_private->ariaDescribedbyElements(describedby);
450 
451     WebVector<WebAXObject> result(describedby.size());
452     for (size_t i = 0; i < describedby.size(); i++)
453         result[i] = WebAXObject(describedby[i]);
454     describedbyElements.swap(result);
455 
456     return true;
457 }
458 
ariaHasPopup() const459 bool WebAXObject::ariaHasPopup() const
460 {
461     if (isDetached())
462         return 0;
463 
464     return m_private->ariaHasPopup();
465 }
466 
ariaFlowTo(WebVector<WebAXObject> & flowToElements) const467 bool WebAXObject::ariaFlowTo(WebVector<WebAXObject>& flowToElements) const
468 {
469     if (isDetached())
470         return false;
471 
472     AXObject::AccessibilityChildrenVector flowTo;
473     m_private->ariaFlowToElements(flowTo);
474 
475     WebVector<WebAXObject> result(flowTo.size());
476     for (size_t i = 0; i < flowTo.size(); i++)
477         result[i] = WebAXObject(flowTo[i]);
478     flowToElements.swap(result);
479 
480     return true;
481 }
482 
ariaLabelledby(WebVector<WebAXObject> & labelledbyElements) const483 bool WebAXObject::ariaLabelledby(WebVector<WebAXObject>& labelledbyElements) const
484 {
485     if (isDetached())
486         return false;
487 
488     AXObject::AccessibilityChildrenVector labelledby;
489     m_private->ariaLabelledbyElements(labelledby);
490 
491     WebVector<WebAXObject> result(labelledby.size());
492     for (size_t i = 0; i < labelledby.size(); i++)
493         result[i] = WebAXObject(labelledby[i]);
494     labelledbyElements.swap(result);
495 
496     return true;
497 }
498 
ariaLiveRegionAtomic() const499 bool WebAXObject::ariaLiveRegionAtomic() const
500 {
501     if (isDetached())
502         return 0;
503 
504     return m_private->ariaLiveRegionAtomic();
505 }
506 
ariaLiveRegionBusy() const507 bool WebAXObject::ariaLiveRegionBusy() const
508 {
509     if (isDetached())
510         return 0;
511 
512     return m_private->ariaLiveRegionBusy();
513 }
514 
ariaLiveRegionRelevant() const515 WebString WebAXObject::ariaLiveRegionRelevant() const
516 {
517     if (isDetached())
518         return WebString();
519 
520     return m_private->ariaLiveRegionRelevant();
521 }
522 
ariaLiveRegionStatus() const523 WebString WebAXObject::ariaLiveRegionStatus() const
524 {
525     if (isDetached())
526         return WebString();
527 
528     return m_private->ariaLiveRegionStatus();
529 }
530 
ariaOwns(WebVector<WebAXObject> & ownsElements) const531 bool WebAXObject::ariaOwns(WebVector<WebAXObject>& ownsElements) const
532 {
533     if (isDetached())
534         return false;
535 
536     AXObject::AccessibilityChildrenVector owns;
537     m_private->ariaOwnsElements(owns);
538 
539     WebVector<WebAXObject> result(owns.size());
540     for (size_t i = 0; i < owns.size(); i++)
541         result[i] = WebAXObject(owns[i]);
542     ownsElements.swap(result);
543 
544     return true;
545 }
546 
547 #if ASSERT_ENABLED
isLayoutClean(Document * document)548 static bool isLayoutClean(Document* document)
549 {
550     if (!document || !document->view())
551         return false;
552     return document->lifecycle().state() >= DocumentLifecycle::LayoutClean
553         || (document->lifecycle().state() == DocumentLifecycle::StyleClean && !document->view()->needsLayout());
554 }
555 #endif
556 
boundingBoxRect() const557 WebRect WebAXObject::boundingBoxRect() const
558 {
559     if (isDetached())
560         return WebRect();
561 
562     // It's not safe to call boundingBoxRect if a layout is pending.
563     // Clients should call updateLayoutAndCheckValidity first.
564     ASSERT(isLayoutClean(m_private->document()));
565 
566     return pixelSnappedIntRect(m_private->elementRect());
567 }
568 
canvasHasFallbackContent() const569 bool WebAXObject::canvasHasFallbackContent() const
570 {
571     if (isDetached())
572         return false;
573 
574     return m_private->canvasHasFallbackContent();
575 }
576 
clickPoint() const577 WebPoint WebAXObject::clickPoint() const
578 {
579     if (isDetached())
580         return WebPoint();
581 
582     return WebPoint(m_private->clickPoint());
583 }
584 
colorValue(int & r,int & g,int & b) const585 void WebAXObject::colorValue(int& r, int& g, int& b) const
586 {
587     if (isDetached())
588         return;
589 
590     m_private->colorValue(r, g, b);
591 }
592 
estimatedLoadingProgress() const593 double WebAXObject::estimatedLoadingProgress() const
594 {
595     if (isDetached())
596         return 0.0;
597 
598     return m_private->estimatedLoadingProgress();
599 }
600 
helpText() const601 WebString WebAXObject::helpText() const
602 {
603     if (isDetached())
604         return WebString();
605 
606     return m_private->helpText();
607 }
608 
headingLevel() const609 int WebAXObject::headingLevel() const
610 {
611     if (isDetached())
612         return 0;
613 
614     return m_private->headingLevel();
615 }
616 
hierarchicalLevel() const617 int WebAXObject::hierarchicalLevel() const
618 {
619     if (isDetached())
620         return 0;
621 
622     return m_private->hierarchicalLevel();
623 }
624 
hitTest(const WebPoint & point) const625 WebAXObject WebAXObject::hitTest(const WebPoint& point) const
626 {
627     if (isDetached())
628         return WebAXObject();
629 
630     IntPoint contentsPoint = m_private->documentFrameView()->windowToContents(point);
631     RefPtr<AXObject> hit = m_private->accessibilityHitTest(contentsPoint);
632 
633     if (hit)
634         return WebAXObject(hit);
635 
636     if (m_private->elementRect().contains(contentsPoint))
637         return *this;
638 
639     return WebAXObject();
640 }
641 
keyboardShortcut() const642 WebString WebAXObject::keyboardShortcut() const
643 {
644     if (isDetached())
645         return WebString();
646 
647     String accessKey = m_private->accessKey();
648     if (accessKey.isNull())
649         return WebString();
650 
651     DEFINE_STATIC_LOCAL(String, modifierString, ());
652     if (modifierString.isNull()) {
653         unsigned modifiers = EventHandler::accessKeyModifiers();
654         // Follow the same order as Mozilla MSAA implementation:
655         // Ctrl+Alt+Shift+Meta+key. MSDN states that keyboard shortcut strings
656         // should not be localized and defines the separator as "+".
657         StringBuilder modifierStringBuilder;
658         if (modifiers & PlatformEvent::CtrlKey)
659             modifierStringBuilder.appendLiteral("Ctrl+");
660         if (modifiers & PlatformEvent::AltKey)
661             modifierStringBuilder.appendLiteral("Alt+");
662         if (modifiers & PlatformEvent::ShiftKey)
663             modifierStringBuilder.appendLiteral("Shift+");
664         if (modifiers & PlatformEvent::MetaKey)
665             modifierStringBuilder.appendLiteral("Win+");
666         modifierString = modifierStringBuilder.toString();
667     }
668 
669     return String(modifierString + accessKey);
670 }
671 
performDefaultAction() const672 bool WebAXObject::performDefaultAction() const
673 {
674     if (isDetached())
675         return false;
676 
677     return m_private->performDefaultAction();
678 }
679 
increment() const680 bool WebAXObject::increment() const
681 {
682     if (isDetached())
683         return false;
684 
685     if (canIncrement()) {
686         m_private->increment();
687         return true;
688     }
689     return false;
690 }
691 
decrement() const692 bool WebAXObject::decrement() const
693 {
694     if (isDetached())
695         return false;
696 
697     if (canDecrement()) {
698         m_private->decrement();
699         return true;
700     }
701     return false;
702 }
703 
press() const704 bool WebAXObject::press() const
705 {
706     if (isDetached())
707         return false;
708 
709     return m_private->press();
710 }
711 
role() const712 WebAXRole WebAXObject::role() const
713 {
714     if (isDetached())
715         return blink::WebAXRoleUnknown;
716 
717     return static_cast<WebAXRole>(m_private->roleValue());
718 }
719 
selectionEnd() const720 unsigned WebAXObject::selectionEnd() const
721 {
722     if (isDetached())
723         return 0;
724 
725     return m_private->selectedTextRange().start + m_private->selectedTextRange().length;
726 }
727 
selectionStart() const728 unsigned WebAXObject::selectionStart() const
729 {
730     if (isDetached())
731         return 0;
732 
733     return m_private->selectedTextRange().start;
734 }
735 
selectionEndLineNumber() const736 unsigned WebAXObject::selectionEndLineNumber() const
737 {
738     if (isDetached())
739         return 0;
740 
741     VisiblePosition position = m_private->visiblePositionForIndex(selectionEnd());
742     int lineNumber = m_private->lineForPosition(position);
743     if (lineNumber < 0)
744         return 0;
745     return lineNumber;
746 }
747 
selectionStartLineNumber() const748 unsigned WebAXObject::selectionStartLineNumber() const
749 {
750     if (isDetached())
751         return 0;
752 
753     VisiblePosition position = m_private->visiblePositionForIndex(selectionStart());
754     int lineNumber = m_private->lineForPosition(position);
755     if (lineNumber < 0)
756         return 0;
757     return lineNumber;
758 }
759 
setFocused(bool on) const760 void WebAXObject::setFocused(bool on) const
761 {
762     if (!isDetached())
763         m_private->setFocused(on);
764 }
765 
setSelectedTextRange(int selectionStart,int selectionEnd) const766 void WebAXObject::setSelectedTextRange(int selectionStart, int selectionEnd) const
767 {
768     if (isDetached())
769         return;
770 
771     m_private->setSelectedTextRange(AXObject::PlainTextRange(selectionStart, selectionEnd - selectionStart));
772 }
773 
stringValue() const774 WebString WebAXObject::stringValue() const
775 {
776     if (isDetached())
777         return WebString();
778 
779     return m_private->stringValue();
780 }
781 
title() const782 WebString WebAXObject::title() const
783 {
784     if (isDetached())
785         return WebString();
786 
787     return m_private->title();
788 }
789 
titleUIElement() const790 WebAXObject WebAXObject::titleUIElement() const
791 {
792     if (isDetached())
793         return WebAXObject();
794 
795     if (!m_private->exposesTitleUIElement())
796         return WebAXObject();
797 
798     return WebAXObject(m_private->titleUIElement());
799 }
800 
url() const801 WebURL WebAXObject::url() const
802 {
803     if (isDetached())
804         return WebURL();
805 
806     return m_private->url();
807 }
808 
supportsRangeValue() const809 bool WebAXObject::supportsRangeValue() const
810 {
811     if (isDetached())
812         return false;
813 
814     return m_private->supportsRangeValue();
815 }
816 
valueDescription() const817 WebString WebAXObject::valueDescription() const
818 {
819     if (isDetached())
820         return WebString();
821 
822     return m_private->valueDescription();
823 }
824 
valueForRange() const825 float WebAXObject::valueForRange() const
826 {
827     if (isDetached())
828         return 0.0;
829 
830     return m_private->valueForRange();
831 }
832 
maxValueForRange() const833 float WebAXObject::maxValueForRange() const
834 {
835     if (isDetached())
836         return 0.0;
837 
838     return m_private->maxValueForRange();
839 }
840 
minValueForRange() const841 float WebAXObject::minValueForRange() const
842 {
843     if (isDetached())
844         return 0.0;
845 
846     return m_private->minValueForRange();
847 }
848 
node() const849 WebNode WebAXObject::node() const
850 {
851     if (isDetached())
852         return WebNode();
853 
854     Node* node = m_private->node();
855     if (!node)
856         return WebNode();
857 
858     return WebNode(node);
859 }
860 
document() const861 WebDocument WebAXObject::document() const
862 {
863     if (isDetached())
864         return WebDocument();
865 
866     Document* document = m_private->document();
867     if (!document)
868         return WebDocument();
869 
870     return WebDocument(document);
871 }
872 
hasComputedStyle() const873 bool WebAXObject::hasComputedStyle() const
874 {
875     if (isDetached())
876         return false;
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 false;
885 
886     return node->computedStyle();
887 }
888 
computedStyleDisplay() const889 WebString WebAXObject::computedStyleDisplay() const
890 {
891     if (isDetached())
892         return WebString();
893 
894     Document* document = m_private->document();
895     if (document)
896         document->updateRenderTreeIfNeeded();
897 
898     Node* node = m_private->node();
899     if (!node)
900         return WebString();
901 
902     RenderStyle* renderStyle = node->computedStyle();
903     if (!renderStyle)
904         return WebString();
905 
906     return WebString(CSSPrimitiveValue::create(renderStyle->display())->getStringValue());
907 }
908 
accessibilityIsIgnored() const909 bool WebAXObject::accessibilityIsIgnored() const
910 {
911     if (isDetached())
912         return false;
913 
914     return m_private->accessibilityIsIgnored();
915 }
916 
lineBreaks(WebVector<int> & result) const917 bool WebAXObject::lineBreaks(WebVector<int>& result) const
918 {
919     if (isDetached())
920         return false;
921 
922     Vector<int> lineBreaksVector;
923     m_private->lineBreaks(lineBreaksVector);
924 
925     size_t vectorSize = lineBreaksVector.size();
926     WebVector<int> lineBreaksWebVector(vectorSize);
927     for (size_t i = 0; i< vectorSize; i++)
928         lineBreaksWebVector[i] = lineBreaksVector[i];
929     result.swap(lineBreaksWebVector);
930 
931     return true;
932 }
933 
columnCount() const934 unsigned WebAXObject::columnCount() const
935 {
936     if (isDetached())
937         return false;
938 
939     if (!m_private->isAXTable())
940         return 0;
941 
942     return toAXTable(m_private.get())->columnCount();
943 }
944 
rowCount() const945 unsigned WebAXObject::rowCount() const
946 {
947     if (isDetached())
948         return false;
949 
950     if (!m_private->isAXTable())
951         return 0;
952 
953     return toAXTable(m_private.get())->rowCount();
954 }
955 
cellForColumnAndRow(unsigned column,unsigned row) const956 WebAXObject WebAXObject::cellForColumnAndRow(unsigned column, unsigned row) const
957 {
958     if (isDetached())
959         return WebAXObject();
960 
961     if (!m_private->isAXTable())
962         return WebAXObject();
963 
964     WebCore::AXTableCell* cell = toAXTable(m_private.get())->cellForColumnAndRow(column, row);
965     return WebAXObject(static_cast<WebCore::AXObject*>(cell));
966 }
967 
headerContainerObject() const968 WebAXObject WebAXObject::headerContainerObject() const
969 {
970     if (isDetached())
971         return WebAXObject();
972 
973     if (!m_private->isAXTable())
974         return WebAXObject();
975 
976     return WebAXObject(toAXTable(m_private.get())->headerContainer());
977 }
978 
rowAtIndex(unsigned rowIndex) const979 WebAXObject WebAXObject::rowAtIndex(unsigned rowIndex) const
980 {
981     if (isDetached())
982         return WebAXObject();
983 
984     if (!m_private->isAXTable())
985         return WebAXObject();
986 
987     const AXObject::AccessibilityChildrenVector& rows = toAXTable(m_private.get())->rows();
988     if (rowIndex < rows.size())
989         return WebAXObject(rows[rowIndex]);
990 
991     return WebAXObject();
992 }
993 
columnAtIndex(unsigned columnIndex) const994 WebAXObject WebAXObject::columnAtIndex(unsigned columnIndex) const
995 {
996     if (isDetached())
997         return WebAXObject();
998 
999     if (!m_private->isAXTable())
1000         return WebAXObject();
1001 
1002     const AXObject::AccessibilityChildrenVector& columns = toAXTable(m_private.get())->columns();
1003     if (columnIndex < columns.size())
1004         return WebAXObject(columns[columnIndex]);
1005 
1006     return WebAXObject();
1007 }
1008 
rowIndex() const1009 unsigned WebAXObject::rowIndex() const
1010 {
1011     if (isDetached())
1012         return 0;
1013 
1014     if (!m_private->isTableRow())
1015         return 0;
1016 
1017     return WebCore::toAXTableRow(m_private.get())->rowIndex();
1018 }
1019 
rowHeader() const1020 WebAXObject WebAXObject::rowHeader() const
1021 {
1022     if (isDetached())
1023         return WebAXObject();
1024 
1025     if (!m_private->isTableRow())
1026         return WebAXObject();
1027 
1028     return WebAXObject(WebCore::toAXTableRow(m_private.get())->headerObject());
1029 }
1030 
columnIndex() const1031 unsigned WebAXObject::columnIndex() const
1032 {
1033     if (isDetached())
1034         return 0;
1035 
1036     if (m_private->roleValue() != ColumnRole)
1037         return 0;
1038 
1039     return WebCore::toAXTableColumn(m_private.get())->columnIndex();
1040 }
1041 
columnHeader() const1042 WebAXObject WebAXObject::columnHeader() const
1043 {
1044     if (isDetached())
1045         return WebAXObject();
1046 
1047     if (m_private->roleValue() != ColumnRole)
1048         return WebAXObject();
1049 
1050     return WebAXObject(WebCore::toAXTableColumn(m_private.get())->headerObject());
1051 }
1052 
cellColumnIndex() const1053 unsigned WebAXObject::cellColumnIndex() const
1054 {
1055     if (isDetached())
1056         return 0;
1057 
1058     if (!m_private->isTableCell())
1059         return 0;
1060 
1061     pair<unsigned, unsigned> columnRange;
1062     WebCore::toAXTableCell(m_private.get())->columnIndexRange(columnRange);
1063     return columnRange.first;
1064 }
1065 
cellColumnSpan() const1066 unsigned WebAXObject::cellColumnSpan() const
1067 {
1068     if (isDetached())
1069         return 0;
1070 
1071     if (!m_private->isTableCell())
1072         return 0;
1073 
1074     pair<unsigned, unsigned> columnRange;
1075     WebCore::toAXTableCell(m_private.get())->columnIndexRange(columnRange);
1076     return columnRange.second;
1077 }
1078 
cellRowIndex() const1079 unsigned WebAXObject::cellRowIndex() const
1080 {
1081     if (isDetached())
1082         return 0;
1083 
1084     if (!m_private->isTableCell())
1085         return 0;
1086 
1087     pair<unsigned, unsigned> rowRange;
1088     WebCore::toAXTableCell(m_private.get())->rowIndexRange(rowRange);
1089     return rowRange.first;
1090 }
1091 
cellRowSpan() const1092 unsigned WebAXObject::cellRowSpan() const
1093 {
1094     if (isDetached())
1095         return 0;
1096 
1097     if (!m_private->isTableCell())
1098         return 0;
1099 
1100     pair<unsigned, unsigned> rowRange;
1101     WebCore::toAXTableCell(m_private.get())->rowIndexRange(rowRange);
1102     return rowRange.second;
1103 }
1104 
textDirection() const1105 WebAXTextDirection WebAXObject::textDirection() const
1106 {
1107     if (isDetached())
1108         return WebAXTextDirectionLR;
1109 
1110     return static_cast<WebAXTextDirection>(m_private->textDirection());
1111 }
1112 
characterOffsets(WebVector<int> & offsets) const1113 void WebAXObject::characterOffsets(WebVector<int>& offsets) const
1114 {
1115     if (isDetached())
1116         return;
1117 
1118     Vector<int> offsetsVector;
1119     m_private->textCharacterOffsets(offsetsVector);
1120 
1121     size_t vectorSize = offsetsVector.size();
1122     WebVector<int> offsetsWebVector(vectorSize);
1123     for (size_t i = 0; i < vectorSize; i++)
1124         offsetsWebVector[i] = offsetsVector[i];
1125     offsets.swap(offsetsWebVector);
1126 }
1127 
wordBoundaries(WebVector<int> & starts,WebVector<int> & ends) const1128 void WebAXObject::wordBoundaries(WebVector<int>& starts, WebVector<int>& ends) const
1129 {
1130     if (isDetached())
1131         return;
1132 
1133     Vector<AXObject::PlainTextRange> words;
1134     m_private->wordBoundaries(words);
1135 
1136     WebVector<int> startsWebVector(words.size());
1137     WebVector<int> endsWebVector(words.size());
1138     for (size_t i = 0; i < words.size(); i++) {
1139         startsWebVector[i] = words[i].start;
1140         endsWebVector[i] = words[i].start + words[i].length;
1141     }
1142     starts.swap(startsWebVector);
1143     ends.swap(endsWebVector);
1144 }
1145 
scrollToMakeVisible() const1146 void WebAXObject::scrollToMakeVisible() const
1147 {
1148     if (!isDetached())
1149         m_private->scrollToMakeVisible();
1150 }
1151 
scrollToMakeVisibleWithSubFocus(const WebRect & subfocus) const1152 void WebAXObject::scrollToMakeVisibleWithSubFocus(const WebRect& subfocus) const
1153 {
1154     if (!isDetached())
1155         m_private->scrollToMakeVisibleWithSubFocus(subfocus);
1156 }
1157 
scrollToGlobalPoint(const WebPoint & point) const1158 void WebAXObject::scrollToGlobalPoint(const WebPoint& point) const
1159 {
1160     if (!isDetached())
1161         m_private->scrollToGlobalPoint(point);
1162 }
1163 
WebAXObject(const WTF::PassRefPtr<WebCore::AXObject> & object)1164 WebAXObject::WebAXObject(const WTF::PassRefPtr<WebCore::AXObject>& object)
1165     : m_private(object)
1166 {
1167 }
1168 
operator =(const WTF::PassRefPtr<WebCore::AXObject> & object)1169 WebAXObject& WebAXObject::operator=(const WTF::PassRefPtr<WebCore::AXObject>& object)
1170 {
1171     m_private = object;
1172     return *this;
1173 }
1174 
operator WTF::PassRefPtr<WebCore::AXObject>() const1175 WebAXObject::operator WTF::PassRefPtr<WebCore::AXObject>() const
1176 {
1177     return m_private.get();
1178 }
1179 
1180 } // namespace blink
1181