blob: 9d8e9c695a7624d099b3ae1906d29864441b4013 [file] [log] [blame]
/*
* Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "public/web/WebAXObject.h"
#include "core/HTMLNames.h"
#include "core/css/CSSPrimitiveValueMappings.h"
#include "core/dom/Document.h"
#include "core/dom/Node.h"
#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
#include "core/frame/VisualViewport.h"
#include "core/input/EventHandler.h"
#include "core/layout/LayoutView.h"
#include "core/style/ComputedStyle.h"
#include "core/page/Page.h"
#include "modules/accessibility/AXObject.h"
#include "modules/accessibility/AXObjectCacheImpl.h"
#include "modules/accessibility/AXTable.h"
#include "modules/accessibility/AXTableCell.h"
#include "modules/accessibility/AXTableColumn.h"
#include "modules/accessibility/AXTableRow.h"
#include "platform/PlatformKeyboardEvent.h"
#include "public/platform/WebPoint.h"
#include "public/platform/WebRect.h"
#include "public/platform/WebString.h"
#include "public/platform/WebURL.h"
#include "public/web/WebDocument.h"
#include "public/web/WebElement.h"
#include "public/web/WebNode.h"
#include "web/WebLocalFrameImpl.h"
#include "web/WebViewImpl.h"
#include "wtf/text/StringBuilder.h"
namespace blink {
#if ENABLE(ASSERT)
// It's not safe to call some WebAXObject APIs if a layout is pending.
// Clients should call updateLayoutAndCheckValidity first.
static bool isLayoutClean(Document* document)
{
if (!document || !document->view())
return false;
return document->lifecycle().state() >= DocumentLifecycle::LayoutClean
|| ((document->lifecycle().state() == DocumentLifecycle::StyleClean || document->lifecycle().state() == DocumentLifecycle::LayoutSubtreeChangeClean)
&& !document->view()->needsLayout());
}
#endif
WebScopedAXContext::WebScopedAXContext(WebDocument& rootDocument)
: m_private(ScopedAXObjectCache::create(*rootDocument.unwrap<Document>()))
{
}
WebScopedAXContext::~WebScopedAXContext()
{
m_private.reset(0);
}
WebAXObject WebScopedAXContext::root() const
{
return WebAXObject(static_cast<AXObjectCacheImpl*>(m_private->get())->root());
}
void WebAXObject::reset()
{
m_private.reset();
}
void WebAXObject::assign(const WebAXObject& other)
{
m_private = other.m_private;
}
bool WebAXObject::equals(const WebAXObject& n) const
{
return m_private.get() == n.m_private.get();
}
bool WebAXObject::isDetached() const
{
if (m_private.isNull())
return true;
return m_private->isDetached();
}
int WebAXObject::axID() const
{
if (isDetached())
return -1;
return m_private->axObjectID();
}
bool WebAXObject::updateLayoutAndCheckValidity()
{
if (!isDetached()) {
Document* document = m_private->document();
if (!document || !document->topDocument().view())
return false;
document->view()->updateAllLifecyclePhases();
}
// Doing a layout can cause this object to be invalid, so check again.
return !isDetached();
}
WebString WebAXObject::actionVerb() const
{
if (isDetached())
return WebString();
return m_private->actionVerb();
}
bool WebAXObject::canDecrement() const
{
if (isDetached())
return false;
return m_private->isSlider();
}
bool WebAXObject::canIncrement() const
{
if (isDetached())
return false;
return m_private->isSlider();
}
bool WebAXObject::canPress() const
{
if (isDetached())
return false;
return m_private->actionElement() || m_private->isButton() || m_private->isMenuRelated();
}
bool WebAXObject::canSetFocusAttribute() const
{
if (isDetached())
return false;
return m_private->canSetFocusAttribute();
}
bool WebAXObject::canSetValueAttribute() const
{
if (isDetached())
return false;
return m_private->canSetValueAttribute();
}
unsigned WebAXObject::childCount() const
{
if (isDetached())
return 0;
return m_private->children().size();
}
WebAXObject WebAXObject::childAt(unsigned index) const
{
if (isDetached())
return WebAXObject();
if (m_private->children().size() <= index)
return WebAXObject();
return WebAXObject(m_private->children()[index]);
}
WebAXObject WebAXObject::parentObject() const
{
if (isDetached())
return WebAXObject();
return WebAXObject(m_private->parentObject());
}
bool WebAXObject::canSetSelectedAttribute() const
{
if (isDetached())
return false;
return m_private->canSetSelectedAttribute();
}
bool WebAXObject::isAnchor() const
{
if (isDetached())
return false;
return m_private->isAnchor();
}
bool WebAXObject::isAriaReadOnly() const
{
if (isDetached())
return false;
return equalIgnoringCase(m_private->getAttribute(HTMLNames::aria_readonlyAttr), "true");
}
WebString WebAXObject::ariaAutoComplete() const
{
if (isDetached())
return WebString();
return m_private->ariaAutoComplete();
}
bool WebAXObject::isButtonStateMixed() const
{
if (isDetached())
return false;
return m_private->checkboxOrRadioValue() == ButtonStateMixed;
}
bool WebAXObject::isChecked() const
{
if (isDetached())
return false;
return m_private->isChecked();
}
bool WebAXObject::isClickable() const
{
if (isDetached())
return false;
return m_private->isClickable();
}
bool WebAXObject::isCollapsed() const
{
if (isDetached())
return false;
return m_private->isCollapsed();
}
bool WebAXObject::isControl() const
{
if (isDetached())
return false;
return m_private->isControl();
}
bool WebAXObject::isEnabled() const
{
if (isDetached())
return false;
return m_private->isEnabled();
}
WebAXExpanded WebAXObject::isExpanded() const
{
if (isDetached())
return WebAXExpandedUndefined;
return static_cast<WebAXExpanded>(m_private->isExpanded());
}
bool WebAXObject::isFocused() const
{
if (isDetached())
return false;
return m_private->isFocused();
}
bool WebAXObject::isHovered() const
{
if (isDetached())
return false;
return m_private->isHovered();
}
bool WebAXObject::isLinked() const
{
if (isDetached())
return false;
return m_private->isLinked();
}
bool WebAXObject::isLoaded() const
{
if (isDetached())
return false;
return m_private->isLoaded();
}
bool WebAXObject::isMultiSelectable() const
{
if (isDetached())
return false;
return m_private->isMultiSelectable();
}
bool WebAXObject::isOffScreen() const
{
if (isDetached())
return false;
return m_private->isOffScreen();
}
bool WebAXObject::isPasswordField() const
{
if (isDetached())
return false;
return m_private->isPasswordField();
}
bool WebAXObject::isPressed() const
{
if (isDetached())
return false;
return m_private->isPressed();
}
bool WebAXObject::isReadOnly() const
{
if (isDetached())
return false;
return m_private->isReadOnly();
}
bool WebAXObject::isRequired() const
{
if (isDetached())
return false;
return m_private->isRequired();
}
bool WebAXObject::isSelected() const
{
if (isDetached())
return false;
return m_private->isSelected();
}
bool WebAXObject::isSelectedOptionActive() const
{
if (isDetached())
return false;
return m_private->isSelectedOptionActive();
}
bool WebAXObject::isVisible() const
{
if (isDetached())
return false;
return m_private->isVisible();
}
bool WebAXObject::isVisited() const
{
if (isDetached())
return false;
return m_private->isVisited();
}
WebString WebAXObject::accessKey() const
{
if (isDetached())
return WebString();
return WebString(m_private->accessKey());
}
unsigned WebAXObject::backgroundColor() const
{
if (isDetached())
return 0;
// RGBA32 is an alias for unsigned int.
return m_private->backgroundColor();
}
unsigned WebAXObject::color() const
{
if (isDetached())
return 0;
// RGBA32 is an alias for unsigned int.
return m_private->color();
}
// Deprecated.
void WebAXObject::colorValue(int& r, int& g, int& b) const
{
if (isDetached())
return;
unsigned color = m_private->colorValue();
r = (color >> 16) & 0xFF;
g = (color >> 8) & 0xFF;
b = color & 0xFF;
}
unsigned WebAXObject::colorValue() const
{
if (isDetached())
return 0;
// RGBA32 is an alias for unsigned int.
return m_private->colorValue();
}
WebAXObject WebAXObject::ariaActiveDescendant() const
{
if (isDetached())
return WebAXObject();
return WebAXObject(m_private->activeDescendant());
}
bool WebAXObject::ariaControls(WebVector<WebAXObject>& controlsElements) const
{
if (isDetached())
return false;
AXObject::AXObjectVector controls;
m_private->ariaControlsElements(controls);
WebVector<WebAXObject> result(controls.size());
for (size_t i = 0; i < controls.size(); i++)
result[i] = WebAXObject(controls[i]);
controlsElements.swap(result);
return true;
}
bool WebAXObject::ariaHasPopup() const
{
if (isDetached())
return false;
return m_private->ariaHasPopup();
}
bool WebAXObject::ariaFlowTo(WebVector<WebAXObject>& flowToElements) const
{
if (isDetached())
return false;
AXObject::AXObjectVector flowTo;
m_private->ariaFlowToElements(flowTo);
WebVector<WebAXObject> result(flowTo.size());
for (size_t i = 0; i < flowTo.size(); i++)
result[i] = WebAXObject(flowTo[i]);
flowToElements.swap(result);
return true;
}
bool WebAXObject::isEditable() const
{
if (isDetached())
return false;
return m_private->isEditable();
}
bool WebAXObject::isMultiline() const
{
if (isDetached())
return false;
return m_private->isMultiline();
}
bool WebAXObject::isRichlyEditable() const
{
if (isDetached())
return false;
return m_private->isRichlyEditable();
}
int WebAXObject::posInSet() const
{
if (isDetached())
return 0;
return m_private->posInSet();
}
int WebAXObject::setSize() const
{
if (isDetached())
return 0;
return m_private->setSize();
}
bool WebAXObject::isInLiveRegion() const
{
if (isDetached())
return false;
return 0 != m_private->liveRegionRoot();
}
bool WebAXObject::liveRegionAtomic() const
{
if (isDetached())
return false;
return m_private->liveRegionAtomic();
}
bool WebAXObject::liveRegionBusy() const
{
if (isDetached())
return false;
return m_private->liveRegionBusy();
}
WebString WebAXObject::liveRegionRelevant() const
{
if (isDetached())
return WebString();
return m_private->liveRegionRelevant();
}
WebString WebAXObject::liveRegionStatus() const
{
if (isDetached())
return WebString();
return m_private->liveRegionStatus();
}
bool WebAXObject::containerLiveRegionAtomic() const
{
if (isDetached())
return false;
return m_private->containerLiveRegionAtomic();
}
bool WebAXObject::containerLiveRegionBusy() const
{
if (isDetached())
return false;
return m_private->containerLiveRegionBusy();
}
WebString WebAXObject::containerLiveRegionRelevant() const
{
if (isDetached())
return WebString();
return m_private->containerLiveRegionRelevant();
}
WebString WebAXObject::containerLiveRegionStatus() const
{
if (isDetached())
return WebString();
return m_private->containerLiveRegionStatus();
}
bool WebAXObject::ariaOwns(WebVector<WebAXObject>& ownsElements) const
{
// aria-owns rearranges the accessibility tree rather than just
// exposing an attribute.
// FIXME(dmazzoni): remove this function after we stop calling it
// from Chromium. http://crbug.com/489590
return false;
}
WebRect WebAXObject::boundingBoxRect() const
{
if (isDetached())
return WebRect();
ASSERT(isLayoutClean(m_private->document()));
return pixelSnappedIntRect(m_private->elementRect());
}
float WebAXObject::fontSize() const
{
if (isDetached())
return 0.0f;
return m_private->fontSize();
}
bool WebAXObject::canvasHasFallbackContent() const
{
if (isDetached())
return false;
return m_private->canvasHasFallbackContent();
}
WebPoint WebAXObject::clickPoint() const
{
if (isDetached())
return WebPoint();
return WebPoint(m_private->clickPoint());
}
WebAXInvalidState WebAXObject::invalidState() const
{
if (isDetached())
return WebAXInvalidStateUndefined;
return static_cast<WebAXInvalidState>(m_private->invalidState());
}
// Only used when invalidState() returns WebAXInvalidStateOther.
WebString WebAXObject::ariaInvalidValue() const
{
if (isDetached())
return WebString();
return m_private->ariaInvalidValue();
}
double WebAXObject::estimatedLoadingProgress() const
{
if (isDetached())
return 0.0;
return m_private->estimatedLoadingProgress();
}
int WebAXObject::headingLevel() const
{
if (isDetached())
return 0;
return m_private->headingLevel();
}
int WebAXObject::hierarchicalLevel() const
{
if (isDetached())
return 0;
return m_private->hierarchicalLevel();
}
// FIXME: This method passes in a point that has page scale applied but assumes that (0, 0)
// is the top left of the visual viewport. In other words, the point has the VisualViewport
// scale applied, but not the VisualViewport offset. crbug.com/459591.
WebAXObject WebAXObject::hitTest(const WebPoint& point) const
{
if (isDetached())
return WebAXObject();
IntPoint contentsPoint = m_private->documentFrameView()->soonToBeRemovedUnscaledViewportToContents(point);
AXObject* hit = m_private->accessibilityHitTest(contentsPoint);
if (hit)
return WebAXObject(hit);
if (m_private->elementRect().contains(contentsPoint))
return *this;
return WebAXObject();
}
WebString WebAXObject::keyboardShortcut() const
{
if (isDetached())
return WebString();
String accessKey = m_private->accessKey();
if (accessKey.isNull())
return WebString();
DEFINE_STATIC_LOCAL(String, modifierString, ());
if (modifierString.isNull()) {
unsigned modifiers = EventHandler::accessKeyModifiers();
// Follow the same order as Mozilla MSAA implementation:
// Ctrl+Alt+Shift+Meta+key. MSDN states that keyboard shortcut strings
// should not be localized and defines the separator as "+".
StringBuilder modifierStringBuilder;
if (modifiers & PlatformEvent::CtrlKey)
modifierStringBuilder.appendLiteral("Ctrl+");
if (modifiers & PlatformEvent::AltKey)
modifierStringBuilder.appendLiteral("Alt+");
if (modifiers & PlatformEvent::ShiftKey)
modifierStringBuilder.appendLiteral("Shift+");
if (modifiers & PlatformEvent::MetaKey)
modifierStringBuilder.appendLiteral("Win+");
modifierString = modifierStringBuilder.toString();
}
return String(modifierString + accessKey);
}
WebString WebAXObject::language() const
{
if (isDetached())
return WebString();
return m_private->language();
}
bool WebAXObject::performDefaultAction() const
{
if (isDetached())
return false;
return m_private->performDefaultAction();
}
bool WebAXObject::increment() const
{
if (isDetached())
return false;
if (canIncrement()) {
m_private->increment();
return true;
}
return false;
}
bool WebAXObject::decrement() const
{
if (isDetached())
return false;
if (canDecrement()) {
m_private->decrement();
return true;
}
return false;
}
WebAXOrientation WebAXObject::orientation() const
{
if (isDetached())
return WebAXOrientationUndefined;
return static_cast<WebAXOrientation>(m_private->orientation());
}
bool WebAXObject::press() const
{
if (isDetached())
return false;
return m_private->press();
}
WebAXRole WebAXObject::role() const
{
if (isDetached())
return WebAXRoleUnknown;
return static_cast<WebAXRole>(m_private->roleValue());
}
void WebAXObject::selection(WebAXObject& anchorObject, int& anchorOffset,
WebAXObject& focusObject, int& focusOffset) const
{
if (isDetached()) {
anchorObject = WebAXObject();
anchorOffset = -1;
focusObject = WebAXObject();
focusOffset = -1;
return;
}
AXObject::AXRange axSelection = m_private->selection();
anchorObject = WebAXObject(axSelection.anchorObject);
anchorOffset = axSelection.anchorOffset;
focusObject = WebAXObject(axSelection.focusObject);
focusOffset = axSelection.focusOffset;
return;
}
void WebAXObject::setSelection(const WebAXObject& anchorObject, int anchorOffset,
const WebAXObject& focusObject, int focusOffset) const
{
if (isDetached())
return;
AXObject::AXRange axSelection(anchorObject, anchorOffset,
focusObject, focusOffset);
m_private->setSelection(axSelection);
return;
}
unsigned WebAXObject::selectionEnd() const
{
if (isDetached())
return 0;
AXObject::AXRange axSelection = m_private->selectionUnderObject();
if (axSelection.focusOffset < 0)
return 0;
return axSelection.focusOffset;
}
unsigned WebAXObject::selectionStart() const
{
if (isDetached())
return 0;
AXObject::AXRange axSelection = m_private->selectionUnderObject();
if (axSelection.anchorOffset < 0)
return 0;
return axSelection.anchorOffset;
}
unsigned WebAXObject::selectionEndLineNumber() const
{
if (isDetached())
return 0;
VisiblePosition position = m_private->visiblePositionForIndex(selectionEnd());
int lineNumber = m_private->lineForPosition(position);
if (lineNumber < 0)
return 0;
return lineNumber;
}
unsigned WebAXObject::selectionStartLineNumber() const
{
if (isDetached())
return 0;
VisiblePosition position = m_private->visiblePositionForIndex(selectionStart());
int lineNumber = m_private->lineForPosition(position);
if (lineNumber < 0)
return 0;
return lineNumber;
}
void WebAXObject::setFocused(bool on) const
{
if (!isDetached())
m_private->setFocused(on);
}
void WebAXObject::setSelectedTextRange(int selectionStart, int selectionEnd) const
{
if (isDetached())
return;
m_private->setSelection(AXObject::AXRange(selectionStart, selectionEnd));
}
void WebAXObject::setValue(WebString value) const
{
if (isDetached())
return;
m_private->setValue(value);
}
void WebAXObject::showContextMenu() const
{
if (isDetached())
return;
Node* node = m_private->node();
if (!node)
return;
Element* element = nullptr;
if (node->isElementNode()) {
element = toElement(node);
} else {
node->updateDistribution();
ContainerNode* parent = FlatTreeTraversal::parent(*node);
ASSERT_WITH_SECURITY_IMPLICATION(parent->isElementNode());
element = toElement(parent);
}
if (!element)
return;
LocalFrame* frame = element->document().frame();
if (!frame)
return;
WebViewImpl* view = WebLocalFrameImpl::fromFrame(frame)->viewImpl();
if (!view)
return;
view->showContextMenuForElement(WebElement(element));
}
WebString WebAXObject::stringValue() const
{
if (isDetached())
return WebString();
return m_private->stringValue();
}
WebAXTextDirection WebAXObject::textDirection() const
{
if (isDetached())
return WebAXTextDirectionLR;
return static_cast<WebAXTextDirection>(m_private->textDirection());
}
WebAXTextStyle WebAXObject::textStyle() const
{
if (isDetached())
return WebAXTextStyleNone;
return static_cast<WebAXTextStyle>(m_private->textStyle());
}
WebURL WebAXObject::url() const
{
if (isDetached())
return WebURL();
return m_private->url();
}
WebString WebAXObject::name(WebAXNameFrom& outNameFrom, WebVector<WebAXObject>& outNameObjects) const
{
if (isDetached())
return WebString();
AXNameFrom nameFrom = AXNameFromUninitialized;
HeapVector<Member<AXObject>> nameObjects;
WebString result = m_private->name(nameFrom, &nameObjects);
outNameFrom = static_cast<WebAXNameFrom>(nameFrom);
WebVector<WebAXObject> webNameObjects(nameObjects.size());
for (size_t i = 0; i < nameObjects.size(); i++)
webNameObjects[i] = WebAXObject(nameObjects[i]);
outNameObjects.swap(webNameObjects);
return result;
}
WebString WebAXObject::name() const
{
if (isDetached())
return WebString();
AXNameFrom nameFrom;
HeapVector<Member<AXObject>> nameObjects;
return m_private->name(nameFrom, &nameObjects);
}
WebString WebAXObject::description(WebAXNameFrom nameFrom, WebAXDescriptionFrom& outDescriptionFrom, WebVector<WebAXObject>& outDescriptionObjects) const
{
if (isDetached())
return WebString();
AXDescriptionFrom descriptionFrom = AXDescriptionFromUninitialized;
HeapVector<Member<AXObject>> descriptionObjects;
String result = m_private->description(static_cast<AXNameFrom>(nameFrom), descriptionFrom, &descriptionObjects);
outDescriptionFrom = static_cast<WebAXDescriptionFrom>(descriptionFrom);
WebVector<WebAXObject> webDescriptionObjects(descriptionObjects.size());
for (size_t i = 0; i < descriptionObjects.size(); i++)
webDescriptionObjects[i] = WebAXObject(descriptionObjects[i]);
outDescriptionObjects.swap(webDescriptionObjects);
return result;
}
WebString WebAXObject::placeholder(WebAXNameFrom nameFrom, WebAXDescriptionFrom descriptionFrom) const
{
if (isDetached())
return WebString();
return m_private->placeholder(static_cast<AXNameFrom>(nameFrom), static_cast<AXDescriptionFrom>(descriptionFrom));
}
bool WebAXObject::supportsRangeValue() const
{
if (isDetached())
return false;
return m_private->supportsRangeValue();
}
WebString WebAXObject::valueDescription() const
{
if (isDetached())
return WebString();
return m_private->valueDescription();
}
float WebAXObject::valueForRange() const
{
if (isDetached())
return 0.0;
return m_private->valueForRange();
}
float WebAXObject::maxValueForRange() const
{
if (isDetached())
return 0.0;
return m_private->maxValueForRange();
}
float WebAXObject::minValueForRange() const
{
if (isDetached())
return 0.0;
return m_private->minValueForRange();
}
WebNode WebAXObject::node() const
{
if (isDetached())
return WebNode();
Node* node = m_private->node();
if (!node)
return WebNode();
return WebNode(node);
}
WebDocument WebAXObject::document() const
{
if (isDetached())
return WebDocument();
Document* document = m_private->document();
if (!document)
return WebDocument();
return WebDocument(document);
}
bool WebAXObject::hasComputedStyle() const
{
if (isDetached())
return false;
Document* document = m_private->document();
if (document)
document->updateLayoutTreeIfNeeded();
Node* node = m_private->node();
if (!node)
return false;
return node->ensureComputedStyle();
}
WebString WebAXObject::computedStyleDisplay() const
{
if (isDetached())
return WebString();
Document* document = m_private->document();
if (document)
document->updateLayoutTreeIfNeeded();
Node* node = m_private->node();
if (!node)
return WebString();
const ComputedStyle* computedStyle = node->ensureComputedStyle();
if (!computedStyle)
return WebString();
return WebString(CSSPrimitiveValue::create(computedStyle->display())->cssText());
}
bool WebAXObject::accessibilityIsIgnored() const
{
if (isDetached())
return false;
return m_private->accessibilityIsIgnored();
}
bool WebAXObject::lineBreaks(WebVector<int>& result) const
{
if (isDetached())
return false;
Vector<int> lineBreaksVector;
m_private->lineBreaks(lineBreaksVector);
size_t vectorSize = lineBreaksVector.size();
WebVector<int> lineBreaksWebVector(vectorSize);
for (size_t i = 0; i< vectorSize; i++)
lineBreaksWebVector[i] = lineBreaksVector[i];
result.swap(lineBreaksWebVector);
return true;
}
unsigned WebAXObject::columnCount() const
{
if (isDetached())
return false;
if (!m_private->isAXTable())
return 0;
return toAXTable(m_private.get())->columnCount();
}
unsigned WebAXObject::rowCount() const
{
if (isDetached())
return false;
if (!m_private->isAXTable())
return 0;
return toAXTable(m_private.get())->rowCount();
}
WebAXObject WebAXObject::cellForColumnAndRow(unsigned column, unsigned row) const
{
if (isDetached())
return WebAXObject();
if (!m_private->isAXTable())
return WebAXObject();
AXTableCell* cell = toAXTable(m_private.get())->cellForColumnAndRow(column, row);
return WebAXObject(static_cast<AXObject*>(cell));
}
WebAXObject WebAXObject::headerContainerObject() const
{
if (isDetached())
return WebAXObject();
if (!m_private->isAXTable())
return WebAXObject();
return WebAXObject(toAXTable(m_private.get())->headerContainer());
}
WebAXObject WebAXObject::rowAtIndex(unsigned rowIndex) const
{
if (isDetached())
return WebAXObject();
if (!m_private->isAXTable())
return WebAXObject();
const AXObject::AXObjectVector& rows = toAXTable(m_private.get())->rows();
if (rowIndex < rows.size())
return WebAXObject(rows[rowIndex]);
return WebAXObject();
}
WebAXObject WebAXObject::columnAtIndex(unsigned columnIndex) const
{
if (isDetached())
return WebAXObject();
if (!m_private->isAXTable())
return WebAXObject();
const AXObject::AXObjectVector& columns = toAXTable(m_private.get())->columns();
if (columnIndex < columns.size())
return WebAXObject(columns[columnIndex]);
return WebAXObject();
}
unsigned WebAXObject::rowIndex() const
{
if (isDetached())
return 0;
if (!m_private->isTableRow())
return 0;
return toAXTableRow(m_private.get())->rowIndex();
}
WebAXObject WebAXObject::rowHeader() const
{
if (isDetached())
return WebAXObject();
if (!m_private->isTableRow())
return WebAXObject();
return WebAXObject(toAXTableRow(m_private.get())->headerObject());
}
void WebAXObject::rowHeaders(WebVector<WebAXObject>& rowHeaderElements) const
{
if (isDetached())
return;
if (!m_private->isAXTable())
return;
AXObject::AXObjectVector headers;
toAXTable(m_private.get())->rowHeaders(headers);
size_t headerCount = headers.size();
WebVector<WebAXObject> result(headerCount);
for (size_t i = 0; i < headerCount; i++)
result[i] = WebAXObject(headers[i]);
rowHeaderElements.swap(result);
}
unsigned WebAXObject::columnIndex() const
{
if (isDetached())
return 0;
if (m_private->roleValue() != ColumnRole)
return 0;
return toAXTableColumn(m_private.get())->columnIndex();
}
WebAXObject WebAXObject::columnHeader() const
{
if (isDetached())
return WebAXObject();
if (m_private->roleValue() != ColumnRole)
return WebAXObject();
return WebAXObject(toAXTableColumn(m_private.get())->headerObject());
}
void WebAXObject::columnHeaders(WebVector<WebAXObject>& columnHeaderElements) const
{
if (isDetached())
return;
if (!m_private->isAXTable())
return;
AXObject::AXObjectVector headers;
toAXTable(m_private.get())->columnHeaders(headers);
size_t headerCount = headers.size();
WebVector<WebAXObject> result(headerCount);
for (size_t i = 0; i < headerCount; i++)
result[i] = WebAXObject(headers[i]);
columnHeaderElements.swap(result);
}
unsigned WebAXObject::cellColumnIndex() const
{
if (isDetached())
return 0;
if (!m_private->isTableCell())
return 0;
std::pair<unsigned, unsigned> columnRange;
toAXTableCell(m_private.get())->columnIndexRange(columnRange);
return columnRange.first;
}
unsigned WebAXObject::cellColumnSpan() const
{
if (isDetached())
return 0;
if (!m_private->isTableCell())
return 0;
std::pair<unsigned, unsigned> columnRange;
toAXTableCell(m_private.get())->columnIndexRange(columnRange);
return columnRange.second;
}
unsigned WebAXObject::cellRowIndex() const
{
if (isDetached())
return 0;
if (!m_private->isTableCell())
return 0;
std::pair<unsigned, unsigned> rowRange;
toAXTableCell(m_private.get())->rowIndexRange(rowRange);
return rowRange.first;
}
unsigned WebAXObject::cellRowSpan() const
{
if (isDetached())
return 0;
if (!m_private->isTableCell())
return 0;
std::pair<unsigned, unsigned> rowRange;
toAXTableCell(m_private.get())->rowIndexRange(rowRange);
return rowRange.second;
}
WebAXSortDirection WebAXObject::sortDirection() const
{
if (isDetached())
return WebAXSortDirectionUndefined;
return static_cast<WebAXSortDirection>(m_private->sortDirection());
}
void WebAXObject::loadInlineTextBoxes() const
{
if (isDetached())
return;
m_private->loadInlineTextBoxes();
}
WebAXObject WebAXObject::nextOnLine() const
{
if (isDetached())
return WebAXObject();
return WebAXObject(m_private.get()->nextOnLine());
}
WebAXObject WebAXObject::previousOnLine() const
{
if (isDetached())
return WebAXObject();
return WebAXObject(m_private.get()->previousOnLine());
}
void WebAXObject::characterOffsets(WebVector<int>& offsets) const
{
if (isDetached())
return;
Vector<int> offsetsVector;
m_private->textCharacterOffsets(offsetsVector);
size_t vectorSize = offsetsVector.size();
WebVector<int> offsetsWebVector(vectorSize);
for (size_t i = 0; i < vectorSize; i++)
offsetsWebVector[i] = offsetsVector[i];
offsets.swap(offsetsWebVector);
}
void WebAXObject::wordBoundaries(WebVector<int>& starts, WebVector<int>& ends) const
{
if (isDetached())
return;
Vector<AXObject::AXRange> wordBoundaries;
m_private->wordBoundaries(wordBoundaries);
WebVector<int> wordStartOffsets(wordBoundaries.size());
WebVector<int> wordEndOffsets(wordBoundaries.size());
for (size_t i = 0; i < wordBoundaries.size(); ++i) {
ASSERT(wordBoundaries[i].isSimple());
wordStartOffsets[i] = wordBoundaries[i].anchorOffset;
wordEndOffsets[i] = wordBoundaries[i].focusOffset;
}
starts.swap(wordStartOffsets);
ends.swap(wordEndOffsets);
}
bool WebAXObject::isScrollableContainer() const
{
if (isDetached())
return false;
return m_private->isScrollableContainer();
}
WebPoint WebAXObject::scrollOffset() const
{
if (isDetached())
return WebPoint();
return m_private->scrollOffset();
}
WebPoint WebAXObject::minimumScrollOffset() const
{
if (isDetached())
return WebPoint();
return m_private->minimumScrollOffset();
}
WebPoint WebAXObject::maximumScrollOffset() const
{
if (isDetached())
return WebPoint();
return m_private->maximumScrollOffset();
}
void WebAXObject::setScrollOffset(const WebPoint& offset) const
{
if (isDetached())
return;
m_private->setScrollOffset(offset);
}
void WebAXObject::scrollToMakeVisible() const
{
if (!isDetached())
m_private->scrollToMakeVisible();
}
void WebAXObject::scrollToMakeVisibleWithSubFocus(const WebRect& subfocus) const
{
if (!isDetached())
m_private->scrollToMakeVisibleWithSubFocus(subfocus);
}
void WebAXObject::scrollToGlobalPoint(const WebPoint& point) const
{
if (!isDetached())
m_private->scrollToGlobalPoint(point);
}
WebAXObject::WebAXObject(AXObject* object)
: m_private(object)
{
}
WebAXObject& WebAXObject::operator=(AXObject* object)
{
m_private = object;
return *this;
}
WebAXObject::operator AXObject*() const
{
return m_private.get();
}
} // namespace blink