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 "WebAccessibilityObject.h"
33
34#include "HTMLNames.h"
35#include "WebDocument.h"
36#include "WebNode.h"
37#include "core/accessibility/AXObjectCache.h"
38#include "core/accessibility/AccessibilityObject.h"
39#include "core/accessibility/AccessibilityTable.h"
40#include "core/accessibility/AccessibilityTableCell.h"
41#include "core/accessibility/AccessibilityTableColumn.h"
42#include "core/accessibility/AccessibilityTableRow.h"
43#include "core/css/CSSPrimitiveValueMappings.h"
44#include "core/dom/Document.h"
45#include "core/dom/Node.h"
46#include "core/page/EventHandler.h"
47#include "core/page/FrameView.h"
48#include "core/platform/PlatformKeyboardEvent.h"
49#include "core/rendering/style/RenderStyle.h"
50#include "public/platform/WebPoint.h"
51#include "public/platform/WebRect.h"
52#include "public/platform/WebString.h"
53#include "public/platform/WebURL.h"
54#include "wtf/text/StringBuilder.h"
55
56using namespace WebCore;
57
58namespace WebKit {
59
60void WebAccessibilityObject::reset()
61{
62    m_private.reset();
63}
64
65void WebAccessibilityObject::assign(const WebKit::WebAccessibilityObject& other)
66{
67    m_private = other.m_private;
68}
69
70bool WebAccessibilityObject::equals(const WebAccessibilityObject& n) const
71{
72    return m_private.get() == n.m_private.get();
73}
74
75// static
76void WebAccessibilityObject::enableAccessibility()
77{
78    AXObjectCache::enableAccessibility();
79}
80
81// static
82bool WebAccessibilityObject::accessibilityEnabled()
83{
84    return AXObjectCache::accessibilityEnabled();
85}
86
87void WebAccessibilityObject::startCachingComputedObjectAttributesUntilTreeMutates()
88{
89    m_private->axObjectCache()->startCachingComputedObjectAttributesUntilTreeMutates();
90}
91
92void WebAccessibilityObject::stopCachingComputedObjectAttributes()
93{
94    m_private->axObjectCache()->stopCachingComputedObjectAttributes();
95}
96
97bool WebAccessibilityObject::isDetached() const
98{
99    if (m_private.isNull())
100        return true;
101
102    return m_private->isDetached();
103}
104
105int WebAccessibilityObject::axID() const
106{
107    if (isDetached())
108        return -1;
109
110    return m_private->axObjectID();
111}
112
113bool WebAccessibilityObject::updateBackingStoreAndCheckValidity()
114{
115    if (!isDetached())
116        m_private->updateBackingStore();
117    return !isDetached();
118}
119
120WebString WebAccessibilityObject::accessibilityDescription() const
121{
122    if (isDetached())
123        return WebString();
124
125    return m_private->accessibilityDescription();
126}
127
128WebString WebAccessibilityObject::actionVerb() const
129{
130    if (isDetached())
131        return WebString();
132
133    return m_private->actionVerb();
134}
135
136bool WebAccessibilityObject::canDecrement() const
137{
138    if (isDetached())
139        return false;
140
141    return m_private->isSlider();
142}
143
144bool WebAccessibilityObject::canIncrement() const
145{
146    if (isDetached())
147        return false;
148
149    return m_private->isSlider();
150}
151
152bool WebAccessibilityObject::canPress() const
153{
154    if (isDetached())
155        return false;
156
157    return m_private->actionElement() || m_private->isButton() || m_private->isMenuRelated();
158}
159
160bool WebAccessibilityObject::canSetFocusAttribute() const
161{
162    if (isDetached())
163        return false;
164
165    return m_private->canSetFocusAttribute();
166}
167
168bool WebAccessibilityObject::canSetValueAttribute() const
169{
170    if (isDetached())
171        return false;
172
173    return m_private->canSetValueAttribute();
174}
175
176unsigned WebAccessibilityObject::childCount() const
177{
178    if (isDetached())
179        return 0;
180
181    return m_private->children().size();
182}
183
184WebAccessibilityObject WebAccessibilityObject::childAt(unsigned index) const
185{
186    if (isDetached())
187        return WebAccessibilityObject();
188
189    if (m_private->children().size() <= index)
190        return WebAccessibilityObject();
191
192    return WebAccessibilityObject(m_private->children()[index]);
193}
194
195WebAccessibilityObject WebAccessibilityObject::parentObject() const
196{
197    if (isDetached())
198        return WebAccessibilityObject();
199
200    return WebAccessibilityObject(m_private->parentObject());
201}
202
203bool WebAccessibilityObject::canSetSelectedAttribute() const
204{
205    if (isDetached())
206        return 0;
207
208    return m_private->canSetSelectedAttribute();
209}
210
211bool WebAccessibilityObject::isAnchor() const
212{
213    if (isDetached())
214        return 0;
215
216    return m_private->isAnchor();
217}
218
219bool WebAccessibilityObject::isAriaReadOnly() const
220{
221    if (isDetached())
222        return 0;
223
224    return equalIgnoringCase(m_private->getAttribute(HTMLNames::aria_readonlyAttr), "true");
225}
226
227bool WebAccessibilityObject::isButtonStateMixed() const
228{
229    if (isDetached())
230        return 0;
231
232    return m_private->checkboxOrRadioValue() == ButtonStateMixed;
233}
234
235bool WebAccessibilityObject::isChecked() const
236{
237    if (isDetached())
238        return 0;
239
240    return m_private->isChecked();
241}
242
243bool WebAccessibilityObject::isCollapsed() const
244{
245    if (isDetached())
246        return 0;
247
248    return m_private->isCollapsed();
249}
250
251bool WebAccessibilityObject::isControl() const
252{
253    if (isDetached())
254        return 0;
255
256    return m_private->isControl();
257}
258
259bool WebAccessibilityObject::isEnabled() const
260{
261    if (isDetached())
262        return 0;
263
264    return m_private->isEnabled();
265}
266
267bool WebAccessibilityObject::isFocused() const
268{
269    if (isDetached())
270        return 0;
271
272    return m_private->isFocused();
273}
274
275bool WebAccessibilityObject::isHovered() const
276{
277    if (isDetached())
278        return 0;
279
280    return m_private->isHovered();
281}
282
283bool WebAccessibilityObject::isIndeterminate() const
284{
285    if (isDetached())
286        return 0;
287
288    return m_private->isIndeterminate();
289}
290
291bool WebAccessibilityObject::isLinked() const
292{
293    if (isDetached())
294        return 0;
295
296    return m_private->isLinked();
297}
298
299bool WebAccessibilityObject::isLoaded() const
300{
301    if (isDetached())
302        return 0;
303
304    return m_private->isLoaded();
305}
306
307bool WebAccessibilityObject::isMultiSelectable() const
308{
309    if (isDetached())
310        return 0;
311
312    return m_private->isMultiSelectable();
313}
314
315bool WebAccessibilityObject::isOffScreen() const
316{
317    if (isDetached())
318        return 0;
319
320    return m_private->isOffScreen();
321}
322
323bool WebAccessibilityObject::isPasswordField() const
324{
325    if (isDetached())
326        return 0;
327
328    return m_private->isPasswordField();
329}
330
331bool WebAccessibilityObject::isPressed() const
332{
333    if (isDetached())
334        return 0;
335
336    return m_private->isPressed();
337}
338
339bool WebAccessibilityObject::isReadOnly() const
340{
341    if (isDetached())
342        return 0;
343
344    return m_private->isReadOnly();
345}
346
347bool WebAccessibilityObject::isRequired() const
348{
349    if (isDetached())
350        return 0;
351
352    return m_private->isRequired();
353}
354
355bool WebAccessibilityObject::isSelected() const
356{
357    if (isDetached())
358        return 0;
359
360    return m_private->isSelected();
361}
362
363bool WebAccessibilityObject::isSelectedOptionActive() const
364{
365    if (isDetached())
366        return false;
367
368    return m_private->isSelectedOptionActive();
369}
370
371bool WebAccessibilityObject::isVertical() const
372{
373    if (isDetached())
374        return 0;
375
376    return m_private->orientation() == AccessibilityOrientationVertical;
377}
378
379bool WebAccessibilityObject::isVisible() const
380{
381    if (isDetached())
382        return 0;
383
384    return m_private->isVisible();
385}
386
387bool WebAccessibilityObject::isVisited() const
388{
389    if (isDetached())
390        return 0;
391
392    return m_private->isVisited();
393}
394
395WebString WebAccessibilityObject::accessKey() const
396{
397    if (isDetached())
398        return WebString();
399
400    return WebString(m_private->accessKey());
401}
402
403bool WebAccessibilityObject::ariaHasPopup() const
404{
405    if (isDetached())
406        return 0;
407
408    return m_private->ariaHasPopup();
409}
410
411bool WebAccessibilityObject::ariaLiveRegionAtomic() const
412{
413    if (isDetached())
414        return 0;
415
416    return m_private->ariaLiveRegionAtomic();
417}
418
419bool WebAccessibilityObject::ariaLiveRegionBusy() const
420{
421    if (isDetached())
422        return 0;
423
424    return m_private->ariaLiveRegionBusy();
425}
426
427WebString WebAccessibilityObject::ariaLiveRegionRelevant() const
428{
429    if (isDetached())
430        return WebString();
431
432    return m_private->ariaLiveRegionRelevant();
433}
434
435WebString WebAccessibilityObject::ariaLiveRegionStatus() const
436{
437    if (isDetached())
438        return WebString();
439
440    return m_private->ariaLiveRegionStatus();
441}
442
443WebRect WebAccessibilityObject::boundingBoxRect() const
444{
445    if (isDetached())
446        return WebRect();
447
448    return pixelSnappedIntRect(m_private->elementRect());
449}
450
451bool WebAccessibilityObject::canvasHasFallbackContent() const
452{
453    if (isDetached())
454        return false;
455
456    return m_private->canvasHasFallbackContent();
457}
458
459WebPoint WebAccessibilityObject::clickPoint() const
460{
461    if (isDetached())
462        return WebPoint();
463
464    return WebPoint(m_private->clickPoint());
465}
466
467void WebAccessibilityObject::colorValue(int& r, int& g, int& b) const
468{
469    if (isDetached())
470        return;
471
472    m_private->colorValue(r, g, b);
473}
474
475double WebAccessibilityObject::estimatedLoadingProgress() const
476{
477    if (isDetached())
478        return 0.0;
479
480    return m_private->estimatedLoadingProgress();
481}
482
483WebString WebAccessibilityObject::helpText() const
484{
485    if (isDetached())
486        return WebString();
487
488    return m_private->helpText();
489}
490
491int WebAccessibilityObject::headingLevel() const
492{
493    if (isDetached())
494        return 0;
495
496    return m_private->headingLevel();
497}
498
499int WebAccessibilityObject::hierarchicalLevel() const
500{
501    if (isDetached())
502        return 0;
503
504    return m_private->hierarchicalLevel();
505}
506
507WebAccessibilityObject WebAccessibilityObject::hitTest(const WebPoint& point) const
508{
509    if (isDetached())
510        return WebAccessibilityObject();
511
512    IntPoint contentsPoint = m_private->documentFrameView()->windowToContents(point);
513    RefPtr<AccessibilityObject> hit = m_private->accessibilityHitTest(contentsPoint);
514
515    if (hit)
516        return WebAccessibilityObject(hit);
517
518    if (m_private->elementRect().contains(contentsPoint))
519        return *this;
520
521    return WebAccessibilityObject();
522}
523
524WebString WebAccessibilityObject::keyboardShortcut() const
525{
526    if (isDetached())
527        return WebString();
528
529    String accessKey = m_private->accessKey();
530    if (accessKey.isNull())
531        return WebString();
532
533    DEFINE_STATIC_LOCAL(String, modifierString, ());
534    if (modifierString.isNull()) {
535        unsigned modifiers = EventHandler::accessKeyModifiers();
536        // Follow the same order as Mozilla MSAA implementation:
537        // Ctrl+Alt+Shift+Meta+key. MSDN states that keyboard shortcut strings
538        // should not be localized and defines the separator as "+".
539        StringBuilder modifierStringBuilder;
540        if (modifiers & PlatformEvent::CtrlKey)
541            modifierStringBuilder.appendLiteral("Ctrl+");
542        if (modifiers & PlatformEvent::AltKey)
543            modifierStringBuilder.appendLiteral("Alt+");
544        if (modifiers & PlatformEvent::ShiftKey)
545            modifierStringBuilder.appendLiteral("Shift+");
546        if (modifiers & PlatformEvent::MetaKey)
547            modifierStringBuilder.appendLiteral("Win+");
548        modifierString = modifierStringBuilder.toString();
549    }
550
551    return String(modifierString + accessKey);
552}
553
554bool WebAccessibilityObject::performDefaultAction() const
555{
556    if (isDetached())
557        return false;
558
559    return m_private->performDefaultAction();
560}
561
562bool WebAccessibilityObject::increment() const
563{
564    if (isDetached())
565        return false;
566
567    if (canIncrement()) {
568        m_private->increment();
569        return true;
570    }
571    return false;
572}
573
574bool WebAccessibilityObject::decrement() const
575{
576    if (isDetached())
577        return false;
578
579    if (canDecrement()) {
580        m_private->decrement();
581        return true;
582    }
583    return false;
584}
585
586bool WebAccessibilityObject::press() const
587{
588    if (isDetached())
589        return false;
590
591    return m_private->press();
592}
593
594WebAccessibilityRole WebAccessibilityObject::roleValue() const
595{
596    if (isDetached())
597        return WebKit::WebAccessibilityRoleUnknown;
598
599    return static_cast<WebAccessibilityRole>(m_private->roleValue());
600}
601
602unsigned WebAccessibilityObject::selectionEnd() const
603{
604    if (isDetached())
605        return 0;
606
607    return m_private->selectedTextRange().start + m_private->selectedTextRange().length;
608}
609
610unsigned WebAccessibilityObject::selectionStart() const
611{
612    if (isDetached())
613        return 0;
614
615    return m_private->selectedTextRange().start;
616}
617
618unsigned WebAccessibilityObject::selectionEndLineNumber() const
619{
620    if (isDetached())
621        return 0;
622
623    VisiblePosition position = m_private->visiblePositionForIndex(selectionEnd());
624    int lineNumber = m_private->lineForPosition(position);
625    if (lineNumber < 0)
626        return 0;
627    return lineNumber;
628}
629
630unsigned WebAccessibilityObject::selectionStartLineNumber() const
631{
632    if (isDetached())
633        return 0;
634
635    VisiblePosition position = m_private->visiblePositionForIndex(selectionStart());
636    int lineNumber = m_private->lineForPosition(position);
637    if (lineNumber < 0)
638        return 0;
639    return lineNumber;
640}
641
642void WebAccessibilityObject::setFocused(bool on) const
643{
644    if (!isDetached())
645        m_private->setFocused(on);
646}
647
648void WebAccessibilityObject::setSelectedTextRange(int selectionStart, int selectionEnd) const
649{
650    if (isDetached())
651        return;
652
653    m_private->setSelectedTextRange(PlainTextRange(selectionStart, selectionEnd - selectionStart));
654}
655
656WebString WebAccessibilityObject::stringValue() const
657{
658    if (isDetached())
659        return WebString();
660
661    return m_private->stringValue();
662}
663
664WebString WebAccessibilityObject::title() const
665{
666    if (isDetached())
667        return WebString();
668
669    return m_private->title();
670}
671
672WebAccessibilityObject WebAccessibilityObject::titleUIElement() const
673{
674    if (isDetached())
675        return WebAccessibilityObject();
676
677    if (!m_private->exposesTitleUIElement())
678        return WebAccessibilityObject();
679
680    return WebAccessibilityObject(m_private->titleUIElement());
681}
682
683WebURL WebAccessibilityObject::url() const
684{
685    if (isDetached())
686        return WebURL();
687
688    return m_private->url();
689}
690
691bool WebAccessibilityObject::supportsRangeValue() const
692{
693    if (isDetached())
694        return false;
695
696    return m_private->supportsRangeValue();
697}
698
699WebString WebAccessibilityObject::valueDescription() const
700{
701    if (isDetached())
702        return WebString();
703
704    return m_private->valueDescription();
705}
706
707float WebAccessibilityObject::valueForRange() const
708{
709    if (isDetached())
710        return 0.0;
711
712    return m_private->valueForRange();
713}
714
715float WebAccessibilityObject::maxValueForRange() const
716{
717    if (isDetached())
718        return 0.0;
719
720    return m_private->maxValueForRange();
721}
722
723float WebAccessibilityObject::minValueForRange() const
724{
725    if (isDetached())
726        return 0.0;
727
728    return m_private->minValueForRange();
729}
730
731WebNode WebAccessibilityObject::node() const
732{
733    if (isDetached())
734        return WebNode();
735
736    Node* node = m_private->node();
737    if (!node)
738        return WebNode();
739
740    return WebNode(node);
741}
742
743WebDocument WebAccessibilityObject::document() const
744{
745    if (isDetached())
746        return WebDocument();
747
748    Document* document = m_private->document();
749    if (!document)
750        return WebDocument();
751
752    return WebDocument(document);
753}
754
755bool WebAccessibilityObject::hasComputedStyle() const
756{
757    if (isDetached())
758        return false;
759
760    Document* document = m_private->document();
761    if (document)
762        document->updateStyleIfNeeded();
763
764    Node* node = m_private->node();
765    if (!node)
766        return false;
767
768    return node->computedStyle();
769}
770
771WebString WebAccessibilityObject::computedStyleDisplay() const
772{
773    if (isDetached())
774        return WebString();
775
776    Document* document = m_private->document();
777    if (document)
778        document->updateStyleIfNeeded();
779
780    Node* node = m_private->node();
781    if (!node)
782        return WebString();
783
784    RenderStyle* renderStyle = node->computedStyle();
785    if (!renderStyle)
786        return WebString();
787
788    return WebString(CSSPrimitiveValue::create(renderStyle->display())->getStringValue());
789}
790
791bool WebAccessibilityObject::accessibilityIsIgnored() const
792{
793    if (isDetached())
794        return false;
795
796    return m_private->accessibilityIsIgnored();
797}
798
799bool WebAccessibilityObject::lineBreaks(WebVector<int>& result) const
800{
801    if (isDetached())
802        return false;
803
804    Vector<int> lineBreaksVector;
805    m_private->lineBreaks(lineBreaksVector);
806
807    size_t vectorSize = lineBreaksVector.size();
808    WebVector<int> lineBreaksWebVector(vectorSize);
809    for (size_t i = 0; i< vectorSize; i++)
810        lineBreaksWebVector[i] = lineBreaksVector[i];
811    result.swap(lineBreaksWebVector);
812
813    return true;
814}
815
816unsigned WebAccessibilityObject::columnCount() const
817{
818    if (isDetached())
819        return false;
820
821    if (!m_private->isAccessibilityTable())
822        return 0;
823
824    return static_cast<WebCore::AccessibilityTable*>(m_private.get())->columnCount();
825}
826
827unsigned WebAccessibilityObject::rowCount() const
828{
829    if (isDetached())
830        return false;
831
832    if (!m_private->isAccessibilityTable())
833        return 0;
834
835    return static_cast<WebCore::AccessibilityTable*>(m_private.get())->rowCount();
836}
837
838WebAccessibilityObject WebAccessibilityObject::cellForColumnAndRow(unsigned column, unsigned row) const
839{
840    if (isDetached())
841        return WebAccessibilityObject();
842
843    if (!m_private->isAccessibilityTable())
844        return WebAccessibilityObject();
845
846    WebCore::AccessibilityTableCell* cell = static_cast<WebCore::AccessibilityTable*>(m_private.get())->cellForColumnAndRow(column, row);
847    return WebAccessibilityObject(static_cast<WebCore::AccessibilityObject*>(cell));
848}
849
850WebAccessibilityObject WebAccessibilityObject::headerContainerObject() const
851{
852    if (isDetached())
853        return WebAccessibilityObject();
854
855    if (!m_private->isAccessibilityTable())
856        return WebAccessibilityObject();
857
858    return WebAccessibilityObject(static_cast<WebCore::AccessibilityTable*>(m_private.get())->headerContainer());
859}
860
861WebAccessibilityObject WebAccessibilityObject::rowAtIndex(unsigned int rowIndex) const
862{
863    if (isDetached())
864        return WebAccessibilityObject();
865
866    if (!m_private->isAccessibilityTable())
867        return WebAccessibilityObject();
868
869    const AccessibilityObject::AccessibilityChildrenVector& rows = static_cast<WebCore::AccessibilityTable*>(m_private.get())->rows();
870    if (rowIndex < rows.size())
871        return WebAccessibilityObject(rows[rowIndex]);
872
873    return WebAccessibilityObject();
874}
875
876WebAccessibilityObject WebAccessibilityObject::columnAtIndex(unsigned int columnIndex) const
877{
878    if (isDetached())
879        return WebAccessibilityObject();
880
881    if (!m_private->isAccessibilityTable())
882        return WebAccessibilityObject();
883
884    const AccessibilityObject::AccessibilityChildrenVector& columns = static_cast<WebCore::AccessibilityTable*>(m_private.get())->columns();
885    if (columnIndex < columns.size())
886        return WebAccessibilityObject(columns[columnIndex]);
887
888    return WebAccessibilityObject();
889}
890
891unsigned WebAccessibilityObject::rowIndex() const
892{
893    if (isDetached())
894        return 0;
895
896    if (!m_private->isTableRow())
897        return 0;
898
899    return static_cast<WebCore::AccessibilityTableRow*>(m_private.get())->rowIndex();
900}
901
902WebAccessibilityObject WebAccessibilityObject::rowHeader() const
903{
904    if (isDetached())
905        return WebAccessibilityObject();
906
907    if (!m_private->isTableRow())
908        return WebAccessibilityObject();
909
910    return WebAccessibilityObject(static_cast<WebCore::AccessibilityTableRow*>(m_private.get())->headerObject());
911}
912
913unsigned WebAccessibilityObject::columnIndex() const
914{
915    if (isDetached())
916        return 0;
917
918    if (m_private->roleValue() != ColumnRole)
919        return 0;
920
921    return static_cast<WebCore::AccessibilityTableColumn*>(m_private.get())->columnIndex();
922}
923
924WebAccessibilityObject WebAccessibilityObject::columnHeader() const
925{
926    if (isDetached())
927        return WebAccessibilityObject();
928
929    if (m_private->roleValue() != ColumnRole)
930        return WebAccessibilityObject();
931
932    return WebAccessibilityObject(static_cast<WebCore::AccessibilityTableColumn*>(m_private.get())->headerObject());
933}
934
935unsigned WebAccessibilityObject::cellColumnIndex() const
936{
937    if (isDetached())
938        return 0;
939
940    if (!m_private->isTableCell())
941       return 0;
942
943    pair<unsigned, unsigned> columnRange;
944    static_cast<WebCore::AccessibilityTableCell*>(m_private.get())->columnIndexRange(columnRange);
945    return columnRange.first;
946}
947
948unsigned WebAccessibilityObject::cellColumnSpan() const
949{
950    if (isDetached())
951        return 0;
952
953    if (!m_private->isTableCell())
954       return 0;
955
956    pair<unsigned, unsigned> columnRange;
957    static_cast<WebCore::AccessibilityTableCell*>(m_private.get())->columnIndexRange(columnRange);
958    return columnRange.second;
959}
960
961unsigned WebAccessibilityObject::cellRowIndex() const
962{
963    if (isDetached())
964        return 0;
965
966    if (!m_private->isTableCell())
967       return 0;
968
969    pair<unsigned, unsigned> rowRange;
970    static_cast<WebCore::AccessibilityTableCell*>(m_private.get())->rowIndexRange(rowRange);
971    return rowRange.first;
972}
973
974unsigned WebAccessibilityObject::cellRowSpan() const
975{
976    if (isDetached())
977        return 0;
978
979    if (!m_private->isTableCell())
980       return 0;
981
982    pair<unsigned, unsigned> rowRange;
983    static_cast<WebCore::AccessibilityTableCell*>(m_private.get())->rowIndexRange(rowRange);
984    return rowRange.second;
985}
986
987void WebAccessibilityObject::scrollToMakeVisible() const
988{
989    if (!isDetached())
990        m_private->scrollToMakeVisible();
991}
992
993void WebAccessibilityObject::scrollToMakeVisibleWithSubFocus(const WebRect& subfocus) const
994{
995    if (!isDetached())
996        m_private->scrollToMakeVisibleWithSubFocus(subfocus);
997}
998
999void WebAccessibilityObject::scrollToGlobalPoint(const WebPoint& point) const
1000{
1001    if (!isDetached())
1002        m_private->scrollToGlobalPoint(point);
1003}
1004
1005WebAccessibilityObject::WebAccessibilityObject(const WTF::PassRefPtr<WebCore::AccessibilityObject>& object)
1006    : m_private(object)
1007{
1008}
1009
1010WebAccessibilityObject& WebAccessibilityObject::operator=(const WTF::PassRefPtr<WebCore::AccessibilityObject>& object)
1011{
1012    m_private = object;
1013    return *this;
1014}
1015
1016WebAccessibilityObject::operator WTF::PassRefPtr<WebCore::AccessibilityObject>() const
1017{
1018    return m_private.get();
1019}
1020
1021} // namespace WebKit
1022