xpcAccessible.cpp (16129B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "AccAttributes.h" 8 #include "nsAccUtils.h" 9 #include "nsComponentManagerUtils.h" 10 #include "nsIAccessibleRelation.h" 11 #include "nsIAccessibleRole.h" 12 #include "nsAccessibleRelation.h" 13 #include "Relation.h" 14 #include "RootAccessible.h" 15 #include "xpcAccessibleDocument.h" 16 17 #include "nsIMutableArray.h" 18 #include "nsPersistentProperties.h" 19 20 #ifdef MOZ_WIDGET_COCOA 21 # include "xpcAccessibleMacInterface.h" 22 #endif 23 24 using namespace mozilla::a11y; 25 26 NS_IMETHODIMP 27 xpcAccessible::GetParent(nsIAccessible** aParent) { 28 NS_ENSURE_ARG_POINTER(aParent); 29 *aParent = nullptr; 30 if (!IntlGeneric()) return NS_ERROR_FAILURE; 31 32 Accessible* parent = IntlGeneric()->Parent(); 33 NS_IF_ADDREF(*aParent = ToXPC(parent)); 34 return NS_OK; 35 } 36 37 NS_IMETHODIMP 38 xpcAccessible::GetNextSibling(nsIAccessible** aNextSibling) { 39 NS_ENSURE_ARG_POINTER(aNextSibling); 40 *aNextSibling = nullptr; 41 if (!IntlGeneric()) return NS_ERROR_FAILURE; 42 43 NS_IF_ADDREF(*aNextSibling = ToXPC(IntlGeneric()->NextSibling())); 44 45 return NS_OK; 46 } 47 48 NS_IMETHODIMP 49 xpcAccessible::GetPreviousSibling(nsIAccessible** aPreviousSibling) { 50 NS_ENSURE_ARG_POINTER(aPreviousSibling); 51 *aPreviousSibling = nullptr; 52 if (!IntlGeneric()) return NS_ERROR_FAILURE; 53 54 NS_IF_ADDREF(*aPreviousSibling = ToXPC(IntlGeneric()->PrevSibling())); 55 56 return NS_OK; 57 } 58 59 NS_IMETHODIMP 60 xpcAccessible::GetFirstChild(nsIAccessible** aFirstChild) { 61 NS_ENSURE_ARG_POINTER(aFirstChild); 62 *aFirstChild = nullptr; 63 64 if (!IntlGeneric()) return NS_ERROR_FAILURE; 65 66 NS_IF_ADDREF(*aFirstChild = ToXPC(IntlGeneric()->FirstChild())); 67 return NS_OK; 68 } 69 70 NS_IMETHODIMP 71 xpcAccessible::GetLastChild(nsIAccessible** aLastChild) { 72 NS_ENSURE_ARG_POINTER(aLastChild); 73 *aLastChild = nullptr; 74 75 if (!IntlGeneric()) return NS_ERROR_FAILURE; 76 77 NS_IF_ADDREF(*aLastChild = ToXPC(IntlGeneric()->LastChild())); 78 return NS_OK; 79 } 80 81 NS_IMETHODIMP 82 xpcAccessible::GetChildCount(int32_t* aChildCount) { 83 NS_ENSURE_ARG_POINTER(aChildCount); 84 85 if (!IntlGeneric()) return NS_ERROR_FAILURE; 86 87 *aChildCount = IntlGeneric()->ChildCount(); 88 return NS_OK; 89 } 90 91 NS_IMETHODIMP 92 xpcAccessible::GetChildAt(int32_t aChildIndex, nsIAccessible** aChild) { 93 NS_ENSURE_ARG_POINTER(aChild); 94 *aChild = nullptr; 95 96 if (!IntlGeneric()) return NS_ERROR_FAILURE; 97 98 // If child index is negative, then return last child. 99 // XXX: do we really need this? 100 if (aChildIndex < 0) aChildIndex = IntlGeneric()->ChildCount() - 1; 101 102 Accessible* child = IntlGeneric()->ChildAt(aChildIndex); 103 if (!child) return NS_ERROR_INVALID_ARG; 104 105 NS_ADDREF(*aChild = ToXPC(child)); 106 return NS_OK; 107 } 108 109 NS_IMETHODIMP 110 xpcAccessible::GetChildren(nsIArray** aChildren) { 111 NS_ENSURE_ARG_POINTER(aChildren); 112 *aChildren = nullptr; 113 114 if (!IntlGeneric()) return NS_ERROR_FAILURE; 115 116 nsresult rv = NS_OK; 117 nsCOMPtr<nsIMutableArray> children = 118 do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); 119 NS_ENSURE_SUCCESS(rv, rv); 120 121 uint32_t childCount = IntlGeneric()->ChildCount(); 122 for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) { 123 Accessible* child = IntlGeneric()->ChildAt(childIdx); 124 children->AppendElement(static_cast<nsIAccessible*>(ToXPC(child))); 125 } 126 127 children.forget(aChildren); 128 return NS_OK; 129 } 130 131 NS_IMETHODIMP 132 xpcAccessible::GetIndexInParent(int32_t* aIndexInParent) { 133 NS_ENSURE_ARG_POINTER(aIndexInParent); 134 *aIndexInParent = -1; 135 if (!IntlGeneric()) return NS_ERROR_FAILURE; 136 137 *aIndexInParent = IntlGeneric()->IndexInParent(); 138 139 return *aIndexInParent != -1 ? NS_OK : NS_ERROR_FAILURE; 140 } 141 142 NS_IMETHODIMP 143 xpcAccessible::GetUniqueID(int64_t* aUniqueID) { 144 NS_ENSURE_ARG_POINTER(aUniqueID); 145 146 if (!IntlGeneric()) return NS_ERROR_FAILURE; 147 148 if (IntlGeneric()->IsLocal()) { 149 *aUniqueID = reinterpret_cast<uintptr_t>(Intl()->UniqueID()); 150 } else if (IntlGeneric()->IsRemote()) { 151 *aUniqueID = IntlGeneric()->AsRemote()->ID(); 152 } 153 154 return NS_OK; 155 } 156 157 NS_IMETHODIMP 158 xpcAccessible::GetDOMNode(nsINode** aDOMNode) { 159 NS_ENSURE_ARG_POINTER(aDOMNode); 160 *aDOMNode = nullptr; 161 162 if (!Intl()) return NS_ERROR_FAILURE; 163 164 nsCOMPtr<nsINode> node = Intl()->GetNode(); 165 node.forget(aDOMNode); 166 167 return NS_OK; 168 } 169 170 NS_IMETHODIMP 171 xpcAccessible::GetId(nsAString& aID) { 172 if (!IntlGeneric()) { 173 return NS_ERROR_FAILURE; 174 } 175 176 nsString id; 177 IntlGeneric()->DOMNodeID(id); 178 aID.Assign(id); 179 180 return NS_OK; 181 } 182 183 NS_IMETHODIMP 184 xpcAccessible::GetDocument(nsIAccessibleDocument** aDocument) { 185 NS_ENSURE_ARG_POINTER(aDocument); 186 *aDocument = nullptr; 187 188 if (!Intl()) return NS_ERROR_FAILURE; 189 190 NS_IF_ADDREF(*aDocument = ToXPCDocument(Intl()->Document())); 191 return NS_OK; 192 } 193 194 NS_IMETHODIMP 195 xpcAccessible::GetRootDocument(nsIAccessibleDocument** aRootDocument) { 196 NS_ENSURE_ARG_POINTER(aRootDocument); 197 *aRootDocument = nullptr; 198 199 if (!Intl()) return NS_ERROR_FAILURE; 200 201 NS_IF_ADDREF(*aRootDocument = ToXPCDocument(Intl()->RootAccessible())); 202 return NS_OK; 203 } 204 205 NS_IMETHODIMP 206 xpcAccessible::GetRole(uint32_t* aRole) { 207 NS_ENSURE_ARG_POINTER(aRole); 208 *aRole = nsIAccessibleRole::ROLE_NOTHING; 209 210 if (!IntlGeneric()) return NS_ERROR_FAILURE; 211 212 *aRole = IntlGeneric()->Role(); 213 return NS_OK; 214 } 215 216 NS_IMETHODIMP 217 xpcAccessible::GetState(uint32_t* aState, uint32_t* aExtraState) { 218 NS_ENSURE_ARG_POINTER(aState); 219 220 Accessible* acc = IntlGeneric(); 221 if (acc) { 222 nsAccUtils::To32States(acc->State(), aState, aExtraState); 223 } else { 224 nsAccUtils::To32States(states::DEFUNCT, aState, aExtraState); 225 } 226 227 return NS_OK; 228 } 229 230 NS_IMETHODIMP 231 xpcAccessible::GetName(nsAString& aName) { 232 aName.Truncate(); 233 234 if (!IntlGeneric()) return NS_ERROR_FAILURE; 235 236 nsAutoString name; 237 IntlGeneric()->Name(name); 238 239 aName.Assign(name); 240 241 return NS_OK; 242 } 243 244 NS_IMETHODIMP 245 xpcAccessible::GetDescription(nsAString& aDescription) { 246 if (!IntlGeneric()) return NS_ERROR_FAILURE; 247 248 nsAutoString desc; 249 IntlGeneric()->Description(desc); 250 251 aDescription.Assign(desc); 252 253 return NS_OK; 254 } 255 256 NS_IMETHODIMP 257 xpcAccessible::GetLanguage(nsAString& aLanguage) { 258 if (!IntlGeneric()) return NS_ERROR_FAILURE; 259 260 nsAutoString lang; 261 IntlGeneric()->Language(lang); 262 263 aLanguage.Assign(lang); 264 return NS_OK; 265 } 266 267 NS_IMETHODIMP 268 xpcAccessible::GetValue(nsAString& aValue) { 269 if (!IntlGeneric()) return NS_ERROR_FAILURE; 270 271 nsAutoString value; 272 IntlGeneric()->Value(value); 273 274 aValue.Assign(value); 275 276 return NS_OK; 277 } 278 279 NS_IMETHODIMP 280 xpcAccessible::GetAccessKey(nsAString& aAccessKey) { 281 aAccessKey.Truncate(); 282 283 if (!IntlGeneric()) return NS_ERROR_FAILURE; 284 285 IntlGeneric()->AccessKey().ToString(aAccessKey); 286 return NS_OK; 287 } 288 289 NS_IMETHODIMP 290 xpcAccessible::GetKeyboardShortcut(nsAString& aKeyBinding) { 291 aKeyBinding.Truncate(); 292 if (!IntlGeneric()) return NS_ERROR_FAILURE; 293 294 if (IntlGeneric()->IsRemote()) { 295 return NS_ERROR_NOT_IMPLEMENTED; 296 } 297 Intl()->KeyboardShortcut().ToString(aKeyBinding); 298 return NS_OK; 299 } 300 301 NS_IMETHODIMP 302 xpcAccessible::GetAttributes(nsIPersistentProperties** aAttributes) { 303 NS_ENSURE_ARG_POINTER(aAttributes); 304 *aAttributes = nullptr; 305 306 Accessible* acc = IntlGeneric(); 307 if (!acc) { 308 return NS_ERROR_FAILURE; 309 } 310 311 RefPtr<nsPersistentProperties> props = new nsPersistentProperties(); 312 313 RefPtr<AccAttributes> attributes = acc->Attributes(); 314 nsAccUtils::SetAccGroupAttrs(attributes, acc); 315 316 nsAutoString unused; 317 for (auto iter : *attributes) { 318 nsAutoString name; 319 iter.NameAsString(name); 320 321 nsAutoString value; 322 iter.ValueAsString(value); 323 324 props->SetStringProperty(NS_ConvertUTF16toUTF8(name), value, unused); 325 } 326 327 props.forget(aAttributes); 328 return NS_OK; 329 } 330 331 NS_IMETHODIMP 332 xpcAccessible::GetCache(nsIPersistentProperties** aCachedFields) { 333 NS_ENSURE_ARG_POINTER(aCachedFields); 334 *aCachedFields = nullptr; 335 336 if (!IntlGeneric()) { 337 return NS_ERROR_FAILURE; 338 } 339 340 RefPtr<nsPersistentProperties> props = new nsPersistentProperties(); 341 if (RemoteAccessible* remoteAcc = IntlGeneric()->AsRemote()) { 342 if (RefPtr<AccAttributes> cachedFields = remoteAcc->mCachedFields) { 343 nsAutoString unused; 344 for (auto iter : *cachedFields) { 345 nsAutoString name; 346 iter.NameAsString(name); 347 348 nsAutoString value; 349 iter.ValueAsString(value); 350 351 props->SetStringProperty(NS_ConvertUTF16toUTF8(name), value, unused); 352 } 353 } 354 } 355 356 props.forget(aCachedFields); 357 return NS_OK; 358 } 359 360 NS_IMETHODIMP 361 xpcAccessible::GetNativeInterface(nsISupports** aNativeInterface) { 362 #ifdef MOZ_WIDGET_COCOA 363 NS_ENSURE_ARG_POINTER(aNativeInterface); 364 365 // We don't cache or store this instance anywhere so each get returns a 366 // different instance. So `acc.nativeInterface != acc.nativeInterface`. This 367 // just seems simpler and more robust for now. 368 nsCOMPtr<nsISupports> macIface = static_cast<nsIAccessibleMacInterface*>( 369 new xpcAccessibleMacInterface(IntlGeneric())); 370 macIface.swap(*aNativeInterface); 371 372 return NS_OK; 373 #else 374 return NS_ERROR_NOT_IMPLEMENTED; 375 #endif 376 } 377 378 NS_IMETHODIMP 379 xpcAccessible::GetBounds(int32_t* aX, int32_t* aY, int32_t* aWidth, 380 int32_t* aHeight) { 381 NS_ENSURE_ARG_POINTER(aX); 382 *aX = 0; 383 NS_ENSURE_ARG_POINTER(aY); 384 *aY = 0; 385 NS_ENSURE_ARG_POINTER(aWidth); 386 *aWidth = 0; 387 NS_ENSURE_ARG_POINTER(aHeight); 388 *aHeight = 0; 389 390 if (!IntlGeneric()) return NS_ERROR_FAILURE; 391 392 LayoutDeviceIntRect rect = IntlGeneric()->Bounds(); 393 rect.GetRect(aX, aY, aWidth, aHeight); 394 return NS_OK; 395 } 396 397 NS_IMETHODIMP 398 xpcAccessible::GetBoundsInCSSPixels(int32_t* aX, int32_t* aY, int32_t* aWidth, 399 int32_t* aHeight) { 400 NS_ENSURE_ARG_POINTER(aX); 401 *aX = 0; 402 NS_ENSURE_ARG_POINTER(aY); 403 *aY = 0; 404 NS_ENSURE_ARG_POINTER(aWidth); 405 *aWidth = 0; 406 NS_ENSURE_ARG_POINTER(aHeight); 407 *aHeight = 0; 408 409 if (!IntlGeneric()) { 410 return NS_ERROR_FAILURE; 411 } 412 413 nsIntRect rect = IntlGeneric()->BoundsInCSSPixels(); 414 rect.GetRect(aX, aY, aWidth, aHeight); 415 return NS_OK; 416 } 417 418 NS_IMETHODIMP 419 xpcAccessible::GroupPosition(int32_t* aGroupLevel, 420 int32_t* aSimilarItemsInGroup, 421 int32_t* aPositionInGroup) { 422 NS_ENSURE_ARG_POINTER(aGroupLevel); 423 NS_ENSURE_ARG_POINTER(aSimilarItemsInGroup); 424 NS_ENSURE_ARG_POINTER(aPositionInGroup); 425 426 GroupPos groupPos = IntlGeneric()->GroupPosition(); 427 428 *aGroupLevel = groupPos.level; 429 *aSimilarItemsInGroup = groupPos.setSize; 430 *aPositionInGroup = groupPos.posInSet; 431 432 return NS_OK; 433 } 434 435 NS_IMETHODIMP 436 xpcAccessible::GetRelationByType(uint32_t aType, 437 nsIAccessibleRelation** aRelation) { 438 NS_ENSURE_ARG_POINTER(aRelation); 439 *aRelation = nullptr; 440 441 NS_ENSURE_ARG(aType <= static_cast<uint32_t>(RelationType::LAST)); 442 443 if (!IntlGeneric()) return NS_ERROR_FAILURE; 444 445 Relation rel = 446 IntlGeneric()->RelationByType(static_cast<RelationType>(aType)); 447 NS_ADDREF(*aRelation = new nsAccessibleRelation(aType, &rel)); 448 return NS_OK; 449 } 450 451 NS_IMETHODIMP 452 xpcAccessible::GetRelations(nsIArray** aRelations) { 453 NS_ENSURE_ARG_POINTER(aRelations); 454 *aRelations = nullptr; 455 456 if (!IntlGeneric()) return NS_ERROR_FAILURE; 457 458 nsCOMPtr<nsIMutableArray> relations = do_CreateInstance(NS_ARRAY_CONTRACTID); 459 NS_ENSURE_TRUE(relations, NS_ERROR_OUT_OF_MEMORY); 460 461 for (uint32_t type = 0; type <= static_cast<uint32_t>(RelationType::LAST); 462 ++type) { 463 nsCOMPtr<nsIAccessibleRelation> relation; 464 nsresult rv = GetRelationByType(type, getter_AddRefs(relation)); 465 466 if (NS_SUCCEEDED(rv) && relation) { 467 uint32_t targets = 0; 468 relation->GetTargetsCount(&targets); 469 if (targets) relations->AppendElement(relation); 470 } 471 } 472 473 NS_ADDREF(*aRelations = relations); 474 return NS_OK; 475 } 476 477 NS_IMETHODIMP 478 xpcAccessible::GetFocusedChild(nsIAccessible** aChild) { 479 NS_ENSURE_ARG_POINTER(aChild); 480 *aChild = nullptr; 481 482 if (!IntlGeneric()) return NS_ERROR_FAILURE; 483 484 NS_IF_ADDREF(*aChild = ToXPC(IntlGeneric()->FocusedChild())); 485 486 return NS_OK; 487 } 488 489 NS_IMETHODIMP 490 xpcAccessible::GetChildAtPoint(int32_t aX, int32_t aY, 491 nsIAccessible** aAccessible) { 492 NS_ENSURE_ARG_POINTER(aAccessible); 493 *aAccessible = nullptr; 494 495 if (!IntlGeneric()) return NS_ERROR_FAILURE; 496 497 NS_IF_ADDREF(*aAccessible = ToXPC(IntlGeneric()->ChildAtPoint( 498 aX, aY, Accessible::EWhichChildAtPoint::DirectChild))); 499 500 return NS_OK; 501 } 502 503 NS_IMETHODIMP 504 xpcAccessible::GetDeepestChildAtPoint(int32_t aX, int32_t aY, 505 nsIAccessible** aAccessible) { 506 NS_ENSURE_ARG_POINTER(aAccessible); 507 *aAccessible = nullptr; 508 509 if (!IntlGeneric()) return NS_ERROR_FAILURE; 510 511 NS_IF_ADDREF(*aAccessible = ToXPC(IntlGeneric()->ChildAtPoint( 512 aX, aY, Accessible::EWhichChildAtPoint::DeepestChild))); 513 514 return NS_OK; 515 } 516 517 NS_IMETHODIMP 518 xpcAccessible::GetDeepestChildAtPointInProcess(int32_t aX, int32_t aY, 519 nsIAccessible** aAccessible) { 520 NS_ENSURE_ARG_POINTER(aAccessible); 521 *aAccessible = nullptr; 522 523 Accessible* generic = IntlGeneric(); 524 if (!generic || generic->IsRemote()) { 525 return NS_ERROR_FAILURE; 526 } 527 528 NS_IF_ADDREF(*aAccessible = ToXPC(Intl()->LocalChildAtPoint( 529 aX, aY, Accessible::EWhichChildAtPoint::DeepestChild))); 530 return NS_OK; 531 } 532 533 NS_IMETHODIMP 534 xpcAccessible::SetSelected(bool aSelect) { 535 if (!IntlGeneric()) return NS_ERROR_FAILURE; 536 537 IntlGeneric()->SetSelected(aSelect); 538 539 return NS_OK; 540 } 541 542 NS_IMETHODIMP 543 xpcAccessible::TakeSelection() { 544 if (!IntlGeneric()) return NS_ERROR_FAILURE; 545 546 IntlGeneric()->TakeSelection(); 547 548 return NS_OK; 549 } 550 551 NS_IMETHODIMP 552 xpcAccessible::TakeFocus() { 553 if (!IntlGeneric()) return NS_ERROR_FAILURE; 554 555 IntlGeneric()->TakeFocus(); 556 return NS_OK; 557 } 558 559 NS_IMETHODIMP 560 xpcAccessible::GetActionCount(uint8_t* aActionCount) { 561 NS_ENSURE_ARG_POINTER(aActionCount); 562 *aActionCount = 0; 563 if (!IntlGeneric()) return NS_ERROR_FAILURE; 564 565 *aActionCount = IntlGeneric()->ActionCount(); 566 567 return NS_OK; 568 } 569 570 NS_IMETHODIMP 571 xpcAccessible::GetActionName(uint8_t aIndex, nsAString& aName) { 572 aName.Truncate(); 573 574 if (!IntlGeneric()) { 575 return NS_ERROR_FAILURE; 576 } 577 578 if (aIndex >= IntlGeneric()->ActionCount()) { 579 return NS_ERROR_INVALID_ARG; 580 } 581 582 nsAutoString name; 583 IntlGeneric()->ActionNameAt(aIndex, name); 584 585 aName.Assign(name); 586 587 return NS_OK; 588 } 589 590 NS_IMETHODIMP 591 xpcAccessible::GetActionDescription(uint8_t aIndex, nsAString& aDescription) { 592 aDescription.Truncate(); 593 594 if (!IntlGeneric()) { 595 return NS_ERROR_FAILURE; 596 } 597 598 if (aIndex >= IntlGeneric()->ActionCount()) { 599 return NS_ERROR_INVALID_ARG; 600 } 601 602 nsAutoString description; 603 IntlGeneric()->ActionDescriptionAt(aIndex, description); 604 605 aDescription.Assign(description); 606 607 return NS_OK; 608 } 609 610 NS_IMETHODIMP 611 xpcAccessible::DoAction(uint8_t aIndex) { 612 if (!IntlGeneric()) return NS_ERROR_FAILURE; 613 614 return IntlGeneric()->DoAction(aIndex) ? NS_OK : NS_ERROR_INVALID_ARG; 615 } 616 617 NS_IMETHODIMP 618 xpcAccessible::ScrollTo(uint32_t aHow) { 619 if (!IntlGeneric()) return NS_ERROR_FAILURE; 620 621 IntlGeneric()->ScrollTo(aHow); 622 return NS_OK; 623 } 624 625 NS_IMETHODIMP 626 xpcAccessible::ScrollToPoint(uint32_t aCoordinateType, int32_t aX, int32_t aY) { 627 if (!IntlGeneric()) return NS_ERROR_FAILURE; 628 629 IntlGeneric()->ScrollToPoint(aCoordinateType, aX, aY); 630 631 return NS_OK; 632 } 633 634 NS_IMETHODIMP 635 xpcAccessible::Announce(const nsAString& aAnnouncement, uint16_t aPriority) { 636 RemoteAccessible* proxy = IntlGeneric()->AsRemote(); 637 if (proxy) { 638 #if defined(XP_WIN) 639 return NS_ERROR_NOT_IMPLEMENTED; 640 #else 641 nsString announcement(aAnnouncement); 642 proxy->Announce(announcement, aPriority); 643 #endif 644 } else { 645 Intl()->Announce(aAnnouncement, aPriority); 646 } 647 648 return NS_OK; 649 } 650 651 NS_IMETHODIMP 652 xpcAccessible::GetComputedARIARole(nsAString& aRole) { 653 if (!IntlGeneric()) { 654 return NS_ERROR_FAILURE; 655 } 656 657 nsStaticAtom* ariaRole = IntlGeneric()->ComputedARIARole(); 658 if (ariaRole) { 659 ariaRole->ToString(aRole); 660 } 661 662 return NS_OK; 663 }