Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / WebAXObject.cpp
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.
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
71 void WebAXObject::reset()
72 {
73     m_private.reset();
74 }
75
76 void WebAXObject::assign(const WebAXObject& other)
77 {
78     m_private = other.m_private;
79 }
80
81 bool WebAXObject::equals(const WebAXObject& n) const
82 {
83     return m_private.get() == n.m_private.get();
84 }
85
86 bool WebAXObject::isDetached() const
87 {
88     if (m_private.isNull())
89         return true;
90
91     return m_private->isDetached();
92 }
93
94 int WebAXObject::axID() const
95 {
96     if (isDetached())
97         return -1;
98
99     return m_private->axObjectID();
100 }
101
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
115 bool WebAXObject::updateBackingStoreAndCheckValidity()
116 {
117     return updateLayoutAndCheckValidity();
118 }
119
120 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
130 WebString WebAXObject::actionVerb() const
131 {
132     if (isDetached())
133         return WebString();
134
135     return m_private->actionVerb();
136 }
137
138 bool WebAXObject::canDecrement() const
139 {
140     if (isDetached())
141         return false;
142
143     return m_private->isSlider();
144 }
145
146 bool WebAXObject::canIncrement() const
147 {
148     if (isDetached())
149         return false;
150
151     return m_private->isSlider();
152 }
153
154 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
162 bool WebAXObject::canSetFocusAttribute() const
163 {
164     if (isDetached())
165         return false;
166
167     return m_private->canSetFocusAttribute();
168 }
169
170 bool WebAXObject::canSetValueAttribute() const
171 {
172     if (isDetached())
173         return false;
174
175     return m_private->canSetValueAttribute();
176 }
177
178 unsigned WebAXObject::childCount() const
179 {
180     if (isDetached())
181         return 0;
182
183     return m_private->children().size();
184 }
185
186 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
197 WebAXObject WebAXObject::parentObject() const
198 {
199     if (isDetached())
200         return WebAXObject();
201
202     return WebAXObject(m_private->parentObject());
203 }
204
205 bool WebAXObject::canSetSelectedAttribute() const
206 {
207     if (isDetached())
208         return 0;
209
210     return m_private->canSetSelectedAttribute();
211 }
212
213 bool WebAXObject::isAnchor() const
214 {
215     if (isDetached())
216         return 0;
217
218     return m_private->isAnchor();
219 }
220
221 bool WebAXObject::isAriaReadOnly() const
222 {
223     if (isDetached())
224         return 0;
225
226     return equalIgnoringCase(m_private->getAttribute(HTMLNames::aria_readonlyAttr), "true");
227 }
228
229 bool WebAXObject::isButtonStateMixed() const
230 {
231     if (isDetached())
232         return 0;
233
234     return m_private->checkboxOrRadioValue() == ButtonStateMixed;
235 }
236
237 bool WebAXObject::isChecked() const
238 {
239     if (isDetached())
240         return 0;
241
242     return m_private->isChecked();
243 }
244
245 bool WebAXObject::isClickable() const
246 {
247     if (isDetached())
248         return 0;
249
250     return m_private->isClickable();
251 }
252
253 bool WebAXObject::isCollapsed() const
254 {
255     if (isDetached())
256         return 0;
257
258     return m_private->isCollapsed();
259 }
260
261 bool WebAXObject::isControl() const
262 {
263     if (isDetached())
264         return 0;
265
266     return m_private->isControl();
267 }
268
269 bool WebAXObject::isEnabled() const
270 {
271     if (isDetached())
272         return 0;
273
274     return m_private->isEnabled();
275 }
276
277 bool WebAXObject::isFocused() const
278 {
279     if (isDetached())
280         return 0;
281
282     return m_private->isFocused();
283 }
284
285 bool WebAXObject::isHovered() const
286 {
287     if (isDetached())
288         return 0;
289
290     return m_private->isHovered();
291 }
292
293 bool WebAXObject::isIndeterminate() const
294 {
295     if (isDetached())
296         return 0;
297
298     return m_private->isIndeterminate();
299 }
300
301 bool WebAXObject::isLinked() const
302 {
303     if (isDetached())
304         return 0;
305
306     return m_private->isLinked();
307 }
308
309 bool WebAXObject::isLoaded() const
310 {
311     if (isDetached())
312         return 0;
313
314     return m_private->isLoaded();
315 }
316
317 bool WebAXObject::isMultiSelectable() const
318 {
319     if (isDetached())
320         return 0;
321
322     return m_private->isMultiSelectable();
323 }
324
325 bool WebAXObject::isOffScreen() const
326 {
327     if (isDetached())
328         return 0;
329
330     return m_private->isOffScreen();
331 }
332
333 bool WebAXObject::isPasswordField() const
334 {
335     if (isDetached())
336         return 0;
337
338     return m_private->isPasswordField();
339 }
340
341 bool WebAXObject::isPressed() const
342 {
343     if (isDetached())
344         return 0;
345
346     return m_private->isPressed();
347 }
348
349 bool WebAXObject::isReadOnly() const
350 {
351     if (isDetached())
352         return 0;
353
354     return m_private->isReadOnly();
355 }
356
357 bool WebAXObject::isRequired() const
358 {
359     if (isDetached())
360         return 0;
361
362     return m_private->isRequired();
363 }
364
365 bool WebAXObject::isSelected() const
366 {
367     if (isDetached())
368         return 0;
369
370     return m_private->isSelected();
371 }
372
373 bool WebAXObject::isSelectedOptionActive() const
374 {
375     if (isDetached())
376         return false;
377
378     return m_private->isSelectedOptionActive();
379 }
380
381 bool WebAXObject::isVertical() const
382 {
383     if (isDetached())
384         return 0;
385
386     return m_private->orientation() == AccessibilityOrientationVertical;
387 }
388
389 bool WebAXObject::isVisible() const
390 {
391     if (isDetached())
392         return 0;
393
394     return m_private->isVisible();
395 }
396
397 bool WebAXObject::isVisited() const
398 {
399     if (isDetached())
400         return 0;
401
402     return m_private->isVisited();
403 }
404
405 WebString WebAXObject::accessKey() const
406 {
407     if (isDetached())
408         return WebString();
409
410     return WebString(m_private->accessKey());
411 }
412
413 WebAXObject WebAXObject::ariaActiveDescendant() const
414 {
415     if (isDetached())
416         return WebAXObject();
417
418     return WebAXObject(m_private->activeDescendant());
419 }
420
421 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
437 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
453 bool WebAXObject::ariaHasPopup() const
454 {
455     if (isDetached())
456         return 0;
457
458     return m_private->ariaHasPopup();
459 }
460
461 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
477 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
493 bool WebAXObject::ariaLiveRegionAtomic() const
494 {
495     if (isDetached())
496         return 0;
497
498     return m_private->ariaLiveRegionAtomic();
499 }
500
501 bool WebAXObject::ariaLiveRegionBusy() const
502 {
503     if (isDetached())
504         return 0;
505
506     return m_private->ariaLiveRegionBusy();
507 }
508
509 WebString WebAXObject::ariaLiveRegionRelevant() const
510 {
511     if (isDetached())
512         return WebString();
513
514     return m_private->ariaLiveRegionRelevant();
515 }
516
517 WebString WebAXObject::ariaLiveRegionStatus() const
518 {
519     if (isDetached())
520         return WebString();
521
522     return m_private->ariaLiveRegionStatus();
523 }
524
525 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
541 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
551 bool WebAXObject::canvasHasFallbackContent() const
552 {
553     if (isDetached())
554         return false;
555
556     return m_private->canvasHasFallbackContent();
557 }
558
559 WebPoint WebAXObject::clickPoint() const
560 {
561     if (isDetached())
562         return WebPoint();
563
564     return WebPoint(m_private->clickPoint());
565 }
566
567 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
575 double WebAXObject::estimatedLoadingProgress() const
576 {
577     if (isDetached())
578         return 0.0;
579
580     return m_private->estimatedLoadingProgress();
581 }
582
583 WebString WebAXObject::helpText() const
584 {
585     if (isDetached())
586         return WebString();
587
588     return m_private->helpText();
589 }
590
591 int WebAXObject::headingLevel() const
592 {
593     if (isDetached())
594         return 0;
595
596     return m_private->headingLevel();
597 }
598
599 int WebAXObject::hierarchicalLevel() const
600 {
601     if (isDetached())
602         return 0;
603
604     return m_private->hierarchicalLevel();
605 }
606
607 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
624 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
654 bool WebAXObject::performDefaultAction() const
655 {
656     if (isDetached())
657         return false;
658
659     return m_private->performDefaultAction();
660 }
661
662 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
674 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
686 bool WebAXObject::press() const
687 {
688     if (isDetached())
689         return false;
690
691     return m_private->press();
692 }
693
694 WebAXRole WebAXObject::role() const
695 {
696     if (isDetached())
697         return WebAXRoleUnknown;
698
699     return static_cast<WebAXRole>(m_private->roleValue());
700 }
701
702 unsigned WebAXObject::selectionEnd() const
703 {
704     if (isDetached())
705         return 0;
706
707     return m_private->selectedTextRange().start + m_private->selectedTextRange().length;
708 }
709
710 unsigned WebAXObject::selectionStart() const
711 {
712     if (isDetached())
713         return 0;
714
715     return m_private->selectedTextRange().start;
716 }
717
718 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
730 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
742 void WebAXObject::setFocused(bool on) const
743 {
744     if (!isDetached())
745         m_private->setFocused(on);
746 }
747
748 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
756 WebString WebAXObject::stringValue() const
757 {
758     if (isDetached())
759         return WebString();
760
761     return m_private->stringValue();
762 }
763
764 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
774 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
785 WebURL WebAXObject::url() const
786 {
787     if (isDetached())
788         return WebURL();
789
790     return m_private->url();
791 }
792
793 bool WebAXObject::supportsRangeValue() const
794 {
795     if (isDetached())
796         return false;
797
798     return m_private->supportsRangeValue();
799 }
800
801 WebString WebAXObject::valueDescription() const
802 {
803     if (isDetached())
804         return WebString();
805
806     return m_private->valueDescription();
807 }
808
809 float WebAXObject::valueForRange() const
810 {
811     if (isDetached())
812         return 0.0;
813
814     return m_private->valueForRange();
815 }
816
817 float WebAXObject::maxValueForRange() const
818 {
819     if (isDetached())
820         return 0.0;
821
822     return m_private->maxValueForRange();
823 }
824
825 float WebAXObject::minValueForRange() const
826 {
827     if (isDetached())
828         return 0.0;
829
830     return m_private->minValueForRange();
831 }
832
833 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
845 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
857 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
873 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
893 bool WebAXObject::accessibilityIsIgnored() const
894 {
895     if (isDetached())
896         return false;
897
898     return m_private->accessibilityIsIgnored();
899 }
900
901 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
918 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
929 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
940 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
952 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
963 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
978 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
993 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
1004 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
1015 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
1026 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
1037 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
1050 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
1063 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
1076 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
1089 WebAXTextDirection WebAXObject::textDirection() const
1090 {
1091     if (isDetached())
1092         return WebAXTextDirectionLR;
1093
1094     return static_cast<WebAXTextDirection>(m_private->textDirection());
1095 }
1096
1097 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
1112 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
1130 void WebAXObject::scrollToMakeVisible() const
1131 {
1132     if (!isDetached())
1133         m_private->scrollToMakeVisible();
1134 }
1135
1136 void WebAXObject::scrollToMakeVisibleWithSubFocus(const WebRect& subfocus) const
1137 {
1138     if (!isDetached())
1139         m_private->scrollToMakeVisibleWithSubFocus(subfocus);
1140 }
1141
1142 void WebAXObject::scrollToGlobalPoint(const WebPoint& point) const
1143 {
1144     if (!isDetached())
1145         m_private->scrollToGlobalPoint(point);
1146 }
1147
1148 WebAXObject::WebAXObject(const WTF::PassRefPtr<AXObject>& object)
1149     : m_private(object)
1150 {
1151 }
1152
1153 WebAXObject& WebAXObject::operator=(const WTF::PassRefPtr<AXObject>& object)
1154 {
1155     m_private = object;
1156     return *this;
1157 }
1158
1159 WebAXObject::operator WTF::PassRefPtr<AXObject>() const
1160 {
1161     return m_private.get();
1162 }
1163
1164 } // namespace blink