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 "AccessibilityObject.h" 35#include "CSSPrimitiveValueMappings.h" 36#include "Document.h" 37#include "EventHandler.h" 38#include "FrameView.h" 39#include "Node.h" 40#include "PlatformKeyboardEvent.h" 41#include "RenderStyle.h" 42#include "UserGestureIndicator.h" 43#include "WebDocument.h" 44#include "WebNode.h" 45#include "WebPoint.h" 46#include "WebRect.h" 47#include "WebString.h" 48#include "WebURL.h" 49 50using namespace WebCore; 51 52namespace WebKit { 53 54class WebAccessibilityObjectPrivate : public WebCore::AccessibilityObject { 55}; 56 57void WebAccessibilityObject::reset() 58{ 59 assign(0); 60} 61 62void WebAccessibilityObject::assign(const WebKit::WebAccessibilityObject& other) 63{ 64 WebAccessibilityObjectPrivate* p = const_cast<WebAccessibilityObjectPrivate*>(other.m_private); 65 if (p) 66 p->ref(); 67 assign(p); 68} 69 70bool WebAccessibilityObject::equals(const WebAccessibilityObject& n) const 71{ 72 return (m_private == n.m_private); 73} 74 75WebString WebAccessibilityObject::accessibilityDescription() const 76{ 77 if (!m_private) 78 return WebString(); 79 80 m_private->updateBackingStore(); 81 return m_private->accessibilityDescription(); 82} 83 84WebString WebAccessibilityObject::actionVerb() const 85{ 86 if (!m_private) 87 return WebString(); 88 89 m_private->updateBackingStore(); 90 return m_private->actionVerb(); 91} 92 93bool WebAccessibilityObject::canSetFocusAttribute() const 94{ 95 if (!m_private) 96 return false; 97 98 m_private->updateBackingStore(); 99 return m_private->canSetFocusAttribute(); 100} 101 102bool WebAccessibilityObject::canSetValueAttribute() const 103{ 104 if (!m_private) 105 return false; 106 107 m_private->updateBackingStore(); 108 return m_private->canSetValueAttribute(); 109} 110 111bool WebAccessibilityObject::isValid() const 112{ 113 if (!m_private) 114 return false; 115 116 m_private->updateBackingStore(); 117 return m_private->axObjectID(); 118} 119 120unsigned WebAccessibilityObject::childCount() const 121{ 122 if (!m_private) 123 return 0; 124 125 m_private->updateBackingStore(); 126 return m_private->children().size(); 127} 128 129WebAccessibilityObject WebAccessibilityObject::childAt(unsigned index) const 130{ 131 if (!m_private) 132 return WebAccessibilityObject(); 133 134 m_private->updateBackingStore(); 135 if (m_private->children().size() <= index) 136 return WebAccessibilityObject(); 137 138 return WebAccessibilityObject(m_private->children()[index]); 139} 140 141WebAccessibilityObject WebAccessibilityObject::firstChild() const 142{ 143 if (!m_private) 144 return WebAccessibilityObject(); 145 146 m_private->updateBackingStore(); 147 return WebAccessibilityObject(m_private->firstChild()); 148} 149 150WebAccessibilityObject WebAccessibilityObject::focusedChild() const 151{ 152 if (!m_private) 153 return WebAccessibilityObject(); 154 155 m_private->updateBackingStore(); 156 RefPtr<AccessibilityObject> focused = m_private->focusedUIElement(); 157 if (m_private == focused.get() || focused->parentObject() == m_private) 158 return WebAccessibilityObject(focused); 159 160 return WebAccessibilityObject(); 161} 162 163WebAccessibilityObject WebAccessibilityObject::lastChild() const 164{ 165 if (!m_private) 166 return WebAccessibilityObject(); 167 168 m_private->updateBackingStore(); 169 return WebAccessibilityObject(m_private->lastChild()); 170} 171 172 173WebAccessibilityObject WebAccessibilityObject::nextSibling() const 174{ 175 if (!m_private) 176 return WebAccessibilityObject(); 177 178 m_private->updateBackingStore(); 179 return WebAccessibilityObject(m_private->nextSibling()); 180} 181 182WebAccessibilityObject WebAccessibilityObject::parentObject() const 183{ 184 if (!m_private) 185 return WebAccessibilityObject(); 186 187 m_private->updateBackingStore(); 188 return WebAccessibilityObject(m_private->parentObject()); 189} 190 191 192WebAccessibilityObject WebAccessibilityObject::previousSibling() const 193{ 194 if (!m_private) 195 return WebAccessibilityObject(); 196 197 m_private->updateBackingStore(); 198 return WebAccessibilityObject(m_private->previousSibling()); 199} 200 201bool WebAccessibilityObject::canSetSelectedAttribute() const 202{ 203 if (!m_private) 204 return 0; 205 206 m_private->updateBackingStore(); 207 return m_private->canSetSelectedAttribute(); 208} 209 210bool WebAccessibilityObject::isAnchor() const 211{ 212 if (!m_private) 213 return 0; 214 215 m_private->updateBackingStore(); 216 return m_private->isAnchor(); 217} 218 219bool WebAccessibilityObject::isChecked() const 220{ 221 if (!m_private) 222 return 0; 223 224 m_private->updateBackingStore(); 225 return m_private->isChecked(); 226} 227 228bool WebAccessibilityObject::isCollapsed() const 229{ 230 if (!m_private) 231 return 0; 232 233 m_private->updateBackingStore(); 234 return m_private->isCollapsed(); 235} 236 237 238bool WebAccessibilityObject::isFocused() const 239{ 240 if (!m_private) 241 return 0; 242 243 m_private->updateBackingStore(); 244 return m_private->isFocused(); 245} 246 247bool WebAccessibilityObject::isEnabled() const 248{ 249 if (!m_private) 250 return 0; 251 252 m_private->updateBackingStore(); 253 return m_private->isEnabled(); 254} 255 256bool WebAccessibilityObject::isHovered() const 257{ 258 if (!m_private) 259 return 0; 260 261 m_private->updateBackingStore(); 262 return m_private->isHovered(); 263} 264 265bool WebAccessibilityObject::isIndeterminate() const 266{ 267 if (!m_private) 268 return 0; 269 270 m_private->updateBackingStore(); 271 return m_private->isIndeterminate(); 272} 273 274bool WebAccessibilityObject::isLinked() const 275{ 276 if (!m_private) 277 return 0; 278 279 m_private->updateBackingStore(); 280 return m_private->isLinked(); 281} 282 283bool WebAccessibilityObject::isMultiSelectable() const 284{ 285 if (!m_private) 286 return 0; 287 288 m_private->updateBackingStore(); 289 return m_private->isMultiSelectable(); 290} 291 292bool WebAccessibilityObject::isOffScreen() const 293{ 294 if (!m_private) 295 return 0; 296 297 m_private->updateBackingStore(); 298 return m_private->isOffScreen(); 299} 300 301bool WebAccessibilityObject::isPasswordField() const 302{ 303 if (!m_private) 304 return 0; 305 306 m_private->updateBackingStore(); 307 return m_private->isPasswordField(); 308} 309 310bool WebAccessibilityObject::isPressed() const 311{ 312 if (!m_private) 313 return 0; 314 315 m_private->updateBackingStore(); 316 return m_private->isPressed(); 317} 318 319bool WebAccessibilityObject::isReadOnly() const 320{ 321 if (!m_private) 322 return 0; 323 324 m_private->updateBackingStore(); 325 return m_private->isReadOnly(); 326} 327 328bool WebAccessibilityObject::isSelected() const 329{ 330 if (!m_private) 331 return 0; 332 333 m_private->updateBackingStore(); 334 return m_private->isSelected(); 335} 336 337bool WebAccessibilityObject::isVisible() const 338{ 339 if (!m_private) 340 return 0; 341 342 m_private->updateBackingStore(); 343 return m_private->isVisible(); 344} 345 346bool WebAccessibilityObject::isVisited() const 347{ 348 if (!m_private) 349 return 0; 350 351 m_private->updateBackingStore(); 352 return m_private->isVisited(); 353} 354 355WebRect WebAccessibilityObject::boundingBoxRect() const 356{ 357 if (!m_private) 358 return WebRect(); 359 360 m_private->updateBackingStore(); 361 return m_private->boundingBoxRect(); 362} 363 364WebString WebAccessibilityObject::helpText() const 365{ 366 if (!m_private) 367 return WebString(); 368 369 m_private->updateBackingStore(); 370 return m_private->helpText(); 371} 372 373int WebAccessibilityObject::headingLevel() const 374{ 375 if (!m_private) 376 return 0; 377 378 m_private->updateBackingStore(); 379 return m_private->headingLevel(); 380} 381 382WebAccessibilityObject WebAccessibilityObject::hitTest(const WebPoint& point) const 383{ 384 if (!m_private) 385 return WebAccessibilityObject(); 386 387 m_private->updateBackingStore(); 388 IntPoint contentsPoint = m_private->documentFrameView()->windowToContents(point); 389 RefPtr<AccessibilityObject> hit = m_private->accessibilityHitTest(contentsPoint); 390 391 if (hit.get()) 392 return WebAccessibilityObject(hit); 393 394 if (m_private->boundingBoxRect().contains(contentsPoint)) 395 return *this; 396 397 return WebAccessibilityObject(); 398} 399 400WebString WebAccessibilityObject::keyboardShortcut() const 401{ 402 if (!m_private) 403 return WebString(); 404 405 m_private->updateBackingStore(); 406 String accessKey = m_private->accessKey(); 407 if (accessKey.isNull()) 408 return WebString(); 409 410 static String modifierString; 411 if (modifierString.isNull()) { 412 unsigned modifiers = EventHandler::accessKeyModifiers(); 413 // Follow the same order as Mozilla MSAA implementation: 414 // Ctrl+Alt+Shift+Meta+key. MSDN states that keyboard shortcut strings 415 // should not be localized and defines the separator as "+". 416 if (modifiers & PlatformKeyboardEvent::CtrlKey) 417 modifierString += "Ctrl+"; 418 if (modifiers & PlatformKeyboardEvent::AltKey) 419 modifierString += "Alt+"; 420 if (modifiers & PlatformKeyboardEvent::ShiftKey) 421 modifierString += "Shift+"; 422 if (modifiers & PlatformKeyboardEvent::MetaKey) 423 modifierString += "Win+"; 424 } 425 426 return modifierString + accessKey; 427} 428 429bool WebAccessibilityObject::performDefaultAction() const 430{ 431 if (!m_private) 432 return false; 433 434 UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture); 435 436 m_private->updateBackingStore(); 437 return m_private->performDefaultAction(); 438} 439 440WebAccessibilityRole WebAccessibilityObject::roleValue() const 441{ 442 if (!m_private) 443 return WebKit::WebAccessibilityRoleUnknown; 444 445 m_private->updateBackingStore(); 446 return static_cast<WebAccessibilityRole>(m_private->roleValue()); 447} 448 449void WebAccessibilityObject::setFocused(bool on) const 450{ 451 if (m_private) 452 m_private->setFocused(on); 453} 454 455WebString WebAccessibilityObject::stringValue() const 456{ 457 if (!m_private) 458 return WebString(); 459 460 m_private->updateBackingStore(); 461 return m_private->stringValue(); 462} 463 464WebString WebAccessibilityObject::title() const 465{ 466 if (!m_private) 467 return WebString(); 468 469 m_private->updateBackingStore(); 470 return m_private->title(); 471} 472 473WebURL WebAccessibilityObject::url() const 474{ 475 if (!m_private) 476 return WebURL(); 477 478 m_private->updateBackingStore(); 479 return m_private->url(); 480} 481 482WebNode WebAccessibilityObject::node() const 483{ 484 if (!m_private) 485 return WebNode(); 486 487 m_private->updateBackingStore(); 488 489 Node* node = m_private->node(); 490 if (!node) 491 return WebNode(); 492 493 return WebNode(node); 494} 495 496WebDocument WebAccessibilityObject::document() const 497{ 498 if (!m_private) 499 return WebDocument(); 500 501 m_private->updateBackingStore(); 502 503 Document* document = m_private->document(); 504 if (!document) 505 return WebDocument(); 506 507 return WebDocument(document); 508} 509 510bool WebAccessibilityObject::hasComputedStyle() const 511{ 512 Document* document = m_private->document(); 513 if (document) 514 document->updateStyleIfNeeded(); 515 516 Node* node = m_private->node(); 517 if (!node) 518 return false; 519 520 return node->computedStyle(); 521} 522 523WebString WebAccessibilityObject::computedStyleDisplay() const 524{ 525 Document* document = m_private->document(); 526 if (document) 527 document->updateStyleIfNeeded(); 528 529 Node* node = m_private->node(); 530 if (!node) 531 return WebString(); 532 533 RenderStyle* renderStyle = node->computedStyle(); 534 if (!renderStyle) 535 return WebString(); 536 537 return WebString(CSSPrimitiveValue::create(renderStyle->display())->getStringValue()); 538} 539 540bool WebAccessibilityObject::accessibilityIsIgnored() const 541{ 542 m_private->updateBackingStore(); 543 return m_private->accessibilityIsIgnored(); 544} 545 546WebAccessibilityObject::WebAccessibilityObject(const WTF::PassRefPtr<WebCore::AccessibilityObject>& object) 547 : m_private(static_cast<WebAccessibilityObjectPrivate*>(object.releaseRef())) 548{ 549} 550 551WebAccessibilityObject& WebAccessibilityObject::operator=(const WTF::PassRefPtr<WebCore::AccessibilityObject>& object) 552{ 553 assign(static_cast<WebAccessibilityObjectPrivate*>(object.releaseRef())); 554 return *this; 555} 556 557WebAccessibilityObject::operator WTF::PassRefPtr<WebCore::AccessibilityObject>() const 558{ 559 return PassRefPtr<WebCore::AccessibilityObject>(const_cast<WebAccessibilityObjectPrivate*>(m_private)); 560} 561 562void WebAccessibilityObject::assign(WebAccessibilityObjectPrivate* p) 563{ 564 // p is already ref'd for us by the caller 565 if (m_private) 566 m_private->deref(); 567 m_private = p; 568} 569 570} // namespace WebKit 571