OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008, 2009, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008, 2009, 2011 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
11 * notice, this list of conditions and the following disclaimer in the | 11 * notice, this list of conditions and the following disclaimer in the |
12 * documentation and/or other materials provided with the distribution. | 12 * documentation and/or other materials provided with the distribution. |
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of | 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
14 * its contributors may be used to endorse or promote products derived | 14 * its contributors may be used to endorse or promote products derived |
15 * from this software without specific prior written permission. | 15 * from this software without specific prior written permission. |
16 * | 16 * |
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 */ | 27 */ |
28 | 28 |
29 #include "modules/accessibility/AXObject.h" | 29 #include "modules/accessibility/AXObjectImpl.h" |
30 | 30 |
31 #include "SkMatrix44.h" | 31 #include "SkMatrix44.h" |
32 #include "core/InputTypeNames.h" | 32 #include "core/InputTypeNames.h" |
33 #include "core/css/resolver/StyleResolver.h" | 33 #include "core/css/resolver/StyleResolver.h" |
34 #include "core/dom/AccessibleNode.h" | 34 #include "core/dom/AccessibleNode.h" |
35 #include "core/dom/DocumentUserGestureToken.h" | 35 #include "core/dom/DocumentUserGestureToken.h" |
36 #include "core/editing/EditingUtilities.h" | 36 #include "core/editing/EditingUtilities.h" |
37 #include "core/editing/VisibleUnits.h" | 37 #include "core/editing/VisibleUnits.h" |
38 #include "core/frame/FrameView.h" | 38 #include "core/frame/FrameView.h" |
39 #include "core/frame/LocalFrame.h" | 39 #include "core/frame/LocalFrame.h" |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 for (size_t i = 0; i < WTF_ARRAY_LENGTH(kRoles); ++i) | 284 for (size_t i = 0; i < WTF_ARRAY_LENGTH(kRoles); ++i) |
285 role_map->Set(String(kRoles[i].aria_role), kRoles[i].webcore_role); | 285 role_map->Set(String(kRoles[i].aria_role), kRoles[i].webcore_role); |
286 return role_map; | 286 return role_map; |
287 } | 287 } |
288 | 288 |
289 static Vector<AtomicString>* CreateRoleNameVector() { | 289 static Vector<AtomicString>* CreateRoleNameVector() { |
290 Vector<AtomicString>* role_name_vector = new Vector<AtomicString>(kNumRoles); | 290 Vector<AtomicString>* role_name_vector = new Vector<AtomicString>(kNumRoles); |
291 for (int i = 0; i < kNumRoles; i++) | 291 for (int i = 0; i < kNumRoles; i++) |
292 (*role_name_vector)[i] = g_null_atom; | 292 (*role_name_vector)[i] = g_null_atom; |
293 | 293 |
294 for (size_t i = 0; i < WTF_ARRAY_LENGTH(kRoles); ++i) | 294 for (size_t i = 0; i < WTF_ARRAY_LENGTH(kRoles); ++i) { |
295 (*role_name_vector)[kRoles[i].webcore_role] = | 295 (*role_name_vector)[kRoles[i].webcore_role] = |
296 AtomicString(kRoles[i].aria_role); | 296 AtomicString(kRoles[i].aria_role); |
| 297 } |
297 | 298 |
298 for (size_t i = 0; i < WTF_ARRAY_LENGTH(kReverseRoles); ++i) | 299 for (size_t i = 0; i < WTF_ARRAY_LENGTH(kReverseRoles); ++i) { |
299 (*role_name_vector)[kReverseRoles[i].webcore_role] = | 300 (*role_name_vector)[kReverseRoles[i].webcore_role] = |
300 AtomicString(kReverseRoles[i].aria_role); | 301 AtomicString(kReverseRoles[i].aria_role); |
| 302 } |
301 | 303 |
302 return role_name_vector; | 304 return role_name_vector; |
303 } | 305 } |
304 | 306 |
305 static Vector<AtomicString>* CreateInternalRoleNameVector() { | 307 static Vector<AtomicString>* CreateInternalRoleNameVector() { |
306 Vector<AtomicString>* internal_role_name_vector = | 308 Vector<AtomicString>* internal_role_name_vector = |
307 new Vector<AtomicString>(kNumRoles); | 309 new Vector<AtomicString>(kNumRoles); |
308 for (size_t i = 0; i < WTF_ARRAY_LENGTH(kInternalRoles); i++) | 310 for (size_t i = 0; i < WTF_ARRAY_LENGTH(kInternalRoles); i++) { |
309 (*internal_role_name_vector)[kInternalRoles[i].webcore_role] = | 311 (*internal_role_name_vector)[kInternalRoles[i].webcore_role] = |
310 AtomicString(kInternalRoles[i].internal_role_name); | 312 AtomicString(kInternalRoles[i].internal_role_name); |
| 313 } |
311 | 314 |
312 return internal_role_name_vector; | 315 return internal_role_name_vector; |
313 } | 316 } |
314 | 317 |
315 const char* g_aria_widgets[] = { | 318 const char* g_aria_widgets[] = { |
316 // From http://www.w3.org/TR/wai-aria/roles#widget_roles | 319 // From http://www.w3.org/TR/wai-aria/roles#widget_roles |
317 "alert", "alertdialog", "button", "checkbox", "dialog", "gridcell", "link", | 320 "alert", "alertdialog", "button", "checkbox", "dialog", "gridcell", "link", |
318 "log", "marquee", "menuitem", "menuitemcheckbox", "menuitemradio", "option", | 321 "log", "marquee", "menuitem", "menuitemcheckbox", "menuitemradio", "option", |
319 "progressbar", "radio", "scrollbar", "slider", "spinbutton", "status", | 322 "progressbar", "radio", "scrollbar", "slider", "spinbutton", "status", |
320 "tab", "tabpanel", "textbox", "timer", "tooltip", "treeitem", | 323 "tab", "tabpanel", "textbox", "timer", "tooltip", "treeitem", |
(...skipping 16 matching lines...) Expand all Loading... |
337 "aria-disabled", // If it's disabled, it can be made interactive. | 340 "aria-disabled", // If it's disabled, it can be made interactive. |
338 "aria-expanded", "aria-haspopup", "aria-multiselectable", | 341 "aria-expanded", "aria-haspopup", "aria-multiselectable", |
339 "aria-pressed", "aria-required", "aria-selected"}; | 342 "aria-pressed", "aria-required", "aria-selected"}; |
340 | 343 |
341 HTMLDialogElement* GetActiveDialogElement(Node* node) { | 344 HTMLDialogElement* GetActiveDialogElement(Node* node) { |
342 return node->GetDocument().ActiveModalDialog(); | 345 return node->GetDocument().ActiveModalDialog(); |
343 } | 346 } |
344 | 347 |
345 } // namespace | 348 } // namespace |
346 | 349 |
347 unsigned AXObject::number_of_live_ax_objects_ = 0; | 350 unsigned AXObjectImpl::number_of_live_ax_objects_ = 0; |
348 | 351 |
349 AXObject::AXObject(AXObjectCacheImpl& ax_object_cache) | 352 AXObjectImpl::AXObjectImpl(AXObjectCacheImpl& ax_object_cache) |
350 : id_(0), | 353 : id_(0), |
351 have_children_(false), | 354 have_children_(false), |
352 role_(kUnknownRole), | 355 role_(kUnknownRole), |
353 last_known_is_ignored_value_(kDefaultBehavior), | 356 last_known_is_ignored_value_(kDefaultBehavior), |
354 explicit_container_id_(0), | 357 explicit_container_id_(0), |
355 parent_(nullptr), | 358 parent_(nullptr), |
356 last_modification_count_(-1), | 359 last_modification_count_(-1), |
357 cached_is_ignored_(false), | 360 cached_is_ignored_(false), |
358 cached_is_inert_or_aria_hidden_(false), | 361 cached_is_inert_or_aria_hidden_(false), |
359 cached_is_descendant_of_leaf_node_(false), | 362 cached_is_descendant_of_leaf_node_(false), |
360 cached_is_descendant_of_disabled_node_(false), | 363 cached_is_descendant_of_disabled_node_(false), |
361 cached_has_inherited_presentational_role_(false), | 364 cached_has_inherited_presentational_role_(false), |
362 cached_is_presentational_child_(false), | 365 cached_is_presentational_child_(false), |
363 cached_ancestor_exposes_active_descendant_(false), | 366 cached_ancestor_exposes_active_descendant_(false), |
364 cached_live_region_root_(nullptr), | 367 cached_live_region_root_(nullptr), |
365 ax_object_cache_(&ax_object_cache) { | 368 ax_object_cache_(&ax_object_cache) { |
366 ++number_of_live_ax_objects_; | 369 ++number_of_live_ax_objects_; |
367 } | 370 } |
368 | 371 |
369 AXObject::~AXObject() { | 372 AXObjectImpl::~AXObjectImpl() { |
370 DCHECK(IsDetached()); | 373 DCHECK(IsDetached()); |
371 --number_of_live_ax_objects_; | 374 --number_of_live_ax_objects_; |
372 } | 375 } |
373 | 376 |
374 void AXObject::Detach() { | 377 void AXObjectImpl::Detach() { |
375 // Clear any children and call detachFromParent on them so that | 378 // Clear any children and call detachFromParent on them so that |
376 // no children are left with dangling pointers to their parent. | 379 // no children are left with dangling pointers to their parent. |
377 ClearChildren(); | 380 ClearChildren(); |
378 | 381 |
379 ax_object_cache_ = nullptr; | 382 ax_object_cache_ = nullptr; |
380 } | 383 } |
381 | 384 |
382 bool AXObject::IsDetached() const { | 385 bool AXObjectImpl::IsDetached() const { |
383 return !ax_object_cache_; | 386 return !ax_object_cache_; |
384 } | 387 } |
385 | 388 |
386 const AtomicString& AXObject::GetAOMPropertyOrARIAAttribute( | 389 const AtomicString& AXObjectImpl::GetAOMPropertyOrARIAAttribute( |
387 AOMStringProperty property) const { | 390 AOMStringProperty property) const { |
388 Node* node = this->GetNode(); | 391 Node* node = this->GetNode(); |
389 if (!node || !node->IsElementNode()) | 392 if (!node || !node->IsElementNode()) |
390 return g_null_atom; | 393 return g_null_atom; |
391 | 394 |
392 return AccessibleNode::GetProperty(ToElement(node), property); | 395 return AccessibleNode::GetProperty(ToElement(node), property); |
393 } | 396 } |
394 | 397 |
395 bool AXObject::IsARIATextControl() const { | 398 bool AXObjectImpl::IsARIATextControl() const { |
396 return AriaRoleAttribute() == kTextFieldRole || | 399 return AriaRoleAttribute() == kTextFieldRole || |
397 AriaRoleAttribute() == kSearchBoxRole || | 400 AriaRoleAttribute() == kSearchBoxRole || |
398 AriaRoleAttribute() == kComboBoxRole; | 401 AriaRoleAttribute() == kComboBoxRole; |
399 } | 402 } |
400 | 403 |
401 bool AXObject::IsButton() const { | 404 bool AXObjectImpl::IsButton() const { |
402 AccessibilityRole role = RoleValue(); | 405 AccessibilityRole role = RoleValue(); |
403 | 406 |
404 return role == kButtonRole || role == kPopUpButtonRole || | 407 return role == kButtonRole || role == kPopUpButtonRole || |
405 role == kToggleButtonRole; | 408 role == kToggleButtonRole; |
406 } | 409 } |
407 | 410 |
408 bool AXObject::IsCheckable() const { | 411 bool AXObjectImpl::IsCheckable() const { |
409 switch (RoleValue()) { | 412 switch (RoleValue()) { |
410 case kCheckBoxRole: | 413 case kCheckBoxRole: |
411 case kMenuItemCheckBoxRole: | 414 case kMenuItemCheckBoxRole: |
412 case kMenuItemRadioRole: | 415 case kMenuItemRadioRole: |
413 case kRadioButtonRole: | 416 case kRadioButtonRole: |
414 case kSwitchRole: | 417 case kSwitchRole: |
415 return true; | 418 return true; |
416 default: | 419 default: |
417 return false; | 420 return false; |
418 } | 421 } |
419 } | 422 } |
420 | 423 |
421 // Why this is here instead of AXNodeObject: | 424 // Why this is here instead of AXNodeObject: |
422 // Because an AXMenuListOption (<option>) can | 425 // Because an AXMenuListOption (<option>) can |
423 // have an ARIA role of menuitemcheckbox/menuitemradio | 426 // have an ARIA role of menuitemcheckbox/menuitemradio |
424 // yet does not inherit from AXNodeObject | 427 // yet does not inherit from AXNodeObject |
425 AccessibilityButtonState AXObject::CheckedState() const { | 428 AccessibilityButtonState AXObjectImpl::CheckedState() const { |
426 if (!IsCheckable()) | 429 if (!IsCheckable()) |
427 return kButtonStateOff; | 430 return kButtonStateOff; |
428 | 431 |
429 const AtomicString& checkedAttribute = | 432 const AtomicString& checkedAttribute = |
430 GetAOMPropertyOrARIAAttribute(AOMStringProperty::kChecked); | 433 GetAOMPropertyOrARIAAttribute(AOMStringProperty::kChecked); |
431 if (checkedAttribute) { | 434 if (checkedAttribute) { |
432 if (EqualIgnoringASCIICase(checkedAttribute, "true")) | 435 if (EqualIgnoringASCIICase(checkedAttribute, "true")) |
433 return kButtonStateOn; | 436 return kButtonStateOn; |
434 | 437 |
435 if (EqualIgnoringASCIICase(checkedAttribute, "mixed")) { | 438 if (EqualIgnoringASCIICase(checkedAttribute, "mixed")) { |
(...skipping 15 matching lines...) Expand all Loading... |
451 return kButtonStateMixed; | 454 return kButtonStateMixed; |
452 | 455 |
453 if (isHTMLInputElement(*node) && | 456 if (isHTMLInputElement(*node) && |
454 toHTMLInputElement(*node).ShouldAppearChecked()) { | 457 toHTMLInputElement(*node).ShouldAppearChecked()) { |
455 return kButtonStateOn; | 458 return kButtonStateOn; |
456 } | 459 } |
457 | 460 |
458 return kButtonStateOff; | 461 return kButtonStateOff; |
459 } | 462 } |
460 | 463 |
461 bool AXObject::IsNativeInputInMixedState(const Node* node) { | 464 bool AXObjectImpl::IsNativeInputInMixedState(const Node* node) { |
462 if (!isHTMLInputElement(node)) | 465 if (!isHTMLInputElement(node)) |
463 return false; | 466 return false; |
464 | 467 |
465 const HTMLInputElement* input = toHTMLInputElement(node); | 468 const HTMLInputElement* input = toHTMLInputElement(node); |
466 const auto inputType = input->type(); | 469 const auto inputType = input->type(); |
467 if (inputType != InputTypeNames::checkbox && | 470 if (inputType != InputTypeNames::checkbox && |
468 inputType != InputTypeNames::radio) | 471 inputType != InputTypeNames::radio) |
469 return false; | 472 return false; |
470 return input->ShouldAppearIndeterminate(); | 473 return input->ShouldAppearIndeterminate(); |
471 } | 474 } |
472 | 475 |
473 bool AXObject::IsLandmarkRelated() const { | 476 bool AXObjectImpl::IsLandmarkRelated() const { |
474 switch (RoleValue()) { | 477 switch (RoleValue()) { |
475 case kApplicationRole: | 478 case kApplicationRole: |
476 case kArticleRole: | 479 case kArticleRole: |
477 case kBannerRole: | 480 case kBannerRole: |
478 case kComplementaryRole: | 481 case kComplementaryRole: |
479 case kContentInfoRole: | 482 case kContentInfoRole: |
480 case kFooterRole: | 483 case kFooterRole: |
481 case kFormRole: | 484 case kFormRole: |
482 case kMainRole: | 485 case kMainRole: |
483 case kNavigationRole: | 486 case kNavigationRole: |
484 case kRegionRole: | 487 case kRegionRole: |
485 case kSearchRole: | 488 case kSearchRole: |
486 return true; | 489 return true; |
487 default: | 490 default: |
488 return false; | 491 return false; |
489 } | 492 } |
490 } | 493 } |
491 | 494 |
492 bool AXObject::IsMenuRelated() const { | 495 bool AXObjectImpl::IsMenuRelated() const { |
493 switch (RoleValue()) { | 496 switch (RoleValue()) { |
494 case kMenuRole: | 497 case kMenuRole: |
495 case kMenuBarRole: | 498 case kMenuBarRole: |
496 case kMenuButtonRole: | 499 case kMenuButtonRole: |
497 case kMenuItemRole: | 500 case kMenuItemRole: |
498 case kMenuItemCheckBoxRole: | 501 case kMenuItemCheckBoxRole: |
499 case kMenuItemRadioRole: | 502 case kMenuItemRadioRole: |
500 return true; | 503 return true; |
501 default: | 504 default: |
502 return false; | 505 return false; |
503 } | 506 } |
504 } | 507 } |
505 | 508 |
506 bool AXObject::IsPasswordFieldAndShouldHideValue() const { | 509 bool AXObjectImpl::IsPasswordFieldAndShouldHideValue() const { |
507 Settings* settings = GetDocument()->GetSettings(); | 510 Settings* settings = GetDocument()->GetSettings(); |
508 if (!settings || settings->GetAccessibilityPasswordValuesEnabled()) | 511 if (!settings || settings->GetAccessibilityPasswordValuesEnabled()) |
509 return false; | 512 return false; |
510 | 513 |
511 return IsPasswordField(); | 514 return IsPasswordField(); |
512 } | 515 } |
513 | 516 |
514 bool AXObject::IsClickable() const { | 517 bool AXObjectImpl::IsClickable() const { |
515 switch (RoleValue()) { | 518 switch (RoleValue()) { |
516 case kButtonRole: | 519 case kButtonRole: |
517 case kCheckBoxRole: | 520 case kCheckBoxRole: |
518 case kColorWellRole: | 521 case kColorWellRole: |
519 case kComboBoxRole: | 522 case kComboBoxRole: |
520 case kImageMapLinkRole: | 523 case kImageMapLinkRole: |
521 case kLinkRole: | 524 case kLinkRole: |
522 case kListBoxOptionRole: | 525 case kListBoxOptionRole: |
523 case kMenuButtonRole: | 526 case kMenuButtonRole: |
524 case kPopUpButtonRole: | 527 case kPopUpButtonRole: |
525 case kRadioButtonRole: | 528 case kRadioButtonRole: |
526 case kSpinButtonRole: | 529 case kSpinButtonRole: |
527 case kTabRole: | 530 case kTabRole: |
528 case kTextFieldRole: | 531 case kTextFieldRole: |
529 case kToggleButtonRole: | 532 case kToggleButtonRole: |
530 return true; | 533 return true; |
531 default: | 534 default: |
532 return false; | 535 return false; |
533 } | 536 } |
534 } | 537 } |
535 | 538 |
536 bool AXObject::AccessibilityIsIgnored() const { | 539 bool AXObjectImpl::AccessibilityIsIgnored() const { |
537 UpdateCachedAttributeValuesIfNeeded(); | 540 UpdateCachedAttributeValuesIfNeeded(); |
538 return cached_is_ignored_; | 541 return cached_is_ignored_; |
539 } | 542 } |
540 | 543 |
541 void AXObject::UpdateCachedAttributeValuesIfNeeded() const { | 544 void AXObjectImpl::UpdateCachedAttributeValuesIfNeeded() const { |
542 if (IsDetached()) | 545 if (IsDetached()) |
543 return; | 546 return; |
544 | 547 |
545 AXObjectCacheImpl& cache = AxObjectCache(); | 548 AXObjectCacheImpl& cache = AxObjectCache(); |
546 | 549 |
547 if (cache.ModificationCount() == last_modification_count_) | 550 if (cache.ModificationCount() == last_modification_count_) |
548 return; | 551 return; |
549 | 552 |
550 last_modification_count_ = cache.ModificationCount(); | 553 last_modification_count_ = cache.ModificationCount(); |
551 cached_background_color_ = ComputeBackgroundColor(); | 554 cached_background_color_ = ComputeBackgroundColor(); |
552 cached_is_inert_or_aria_hidden_ = ComputeIsInertOrAriaHidden(); | 555 cached_is_inert_or_aria_hidden_ = ComputeIsInertOrAriaHidden(); |
553 cached_is_descendant_of_leaf_node_ = (LeafNodeAncestor() != 0); | 556 cached_is_descendant_of_leaf_node_ = (LeafNodeAncestor() != 0); |
554 cached_is_descendant_of_disabled_node_ = (DisabledAncestor() != 0); | 557 cached_is_descendant_of_disabled_node_ = (DisabledAncestor() != 0); |
555 cached_has_inherited_presentational_role_ = | 558 cached_has_inherited_presentational_role_ = |
556 (InheritsPresentationalRoleFrom() != 0); | 559 (InheritsPresentationalRoleFrom() != 0); |
557 cached_is_presentational_child_ = | 560 cached_is_presentational_child_ = |
558 (AncestorForWhichThisIsAPresentationalChild() != 0); | 561 (AncestorForWhichThisIsAPresentationalChild() != 0); |
559 cached_is_ignored_ = ComputeAccessibilityIsIgnored(); | 562 cached_is_ignored_ = ComputeAccessibilityIsIgnored(); |
560 cached_live_region_root_ = | 563 cached_live_region_root_ = |
561 IsLiveRegion() | 564 IsLiveRegion() |
562 ? const_cast<AXObject*>(this) | 565 ? const_cast<AXObjectImpl*>(this) |
563 : (ParentObjectIfExists() ? ParentObjectIfExists()->LiveRegionRoot() | 566 : (ParentObjectIfExists() ? ParentObjectIfExists()->LiveRegionRoot() |
564 : 0); | 567 : 0); |
565 cached_ancestor_exposes_active_descendant_ = | 568 cached_ancestor_exposes_active_descendant_ = |
566 ComputeAncestorExposesActiveDescendant(); | 569 ComputeAncestorExposesActiveDescendant(); |
567 } | 570 } |
568 | 571 |
569 bool AXObject::AccessibilityIsIgnoredByDefault( | 572 bool AXObjectImpl::AccessibilityIsIgnoredByDefault( |
570 IgnoredReasons* ignored_reasons) const { | 573 IgnoredReasons* ignored_reasons) const { |
571 return DefaultObjectInclusion(ignored_reasons) == kIgnoreObject; | 574 return DefaultObjectInclusion(ignored_reasons) == kIgnoreObject; |
572 } | 575 } |
573 | 576 |
574 AXObjectInclusion AXObject::AccessibilityPlatformIncludesObject() const { | 577 AXObjectInclusion AXObjectImpl::AccessibilityPlatformIncludesObject() const { |
575 if (IsMenuListPopup() || IsMenuListOption()) | 578 if (IsMenuListPopup() || IsMenuListOption()) |
576 return kIncludeObject; | 579 return kIncludeObject; |
577 | 580 |
578 return kDefaultBehavior; | 581 return kDefaultBehavior; |
579 } | 582 } |
580 | 583 |
581 AXObjectInclusion AXObject::DefaultObjectInclusion( | 584 AXObjectInclusion AXObjectImpl::DefaultObjectInclusion( |
582 IgnoredReasons* ignored_reasons) const { | 585 IgnoredReasons* ignored_reasons) const { |
583 if (IsInertOrAriaHidden()) { | 586 if (IsInertOrAriaHidden()) { |
584 if (ignored_reasons) | 587 if (ignored_reasons) |
585 ComputeIsInertOrAriaHidden(ignored_reasons); | 588 ComputeIsInertOrAriaHidden(ignored_reasons); |
586 return kIgnoreObject; | 589 return kIgnoreObject; |
587 } | 590 } |
588 | 591 |
589 if (IsPresentationalChild()) { | 592 if (IsPresentationalChild()) { |
590 if (ignored_reasons) { | 593 if (ignored_reasons) { |
591 AXObject* ancestor = AncestorForWhichThisIsAPresentationalChild(); | 594 AXObjectImpl* ancestor = AncestorForWhichThisIsAPresentationalChild(); |
592 ignored_reasons->push_back( | 595 ignored_reasons->push_back( |
593 IgnoredReason(kAXAncestorDisallowsChild, ancestor)); | 596 IgnoredReason(kAXAncestorDisallowsChild, ancestor)); |
594 } | 597 } |
595 return kIgnoreObject; | 598 return kIgnoreObject; |
596 } | 599 } |
597 | 600 |
598 return AccessibilityPlatformIncludesObject(); | 601 return AccessibilityPlatformIncludesObject(); |
599 } | 602 } |
600 | 603 |
601 bool AXObject::IsInertOrAriaHidden() const { | 604 bool AXObjectImpl::IsInertOrAriaHidden() const { |
602 UpdateCachedAttributeValuesIfNeeded(); | 605 UpdateCachedAttributeValuesIfNeeded(); |
603 return cached_is_inert_or_aria_hidden_; | 606 return cached_is_inert_or_aria_hidden_; |
604 } | 607 } |
605 | 608 |
606 bool AXObject::ComputeIsInertOrAriaHidden( | 609 bool AXObjectImpl::ComputeIsInertOrAriaHidden( |
607 IgnoredReasons* ignored_reasons) const { | 610 IgnoredReasons* ignored_reasons) const { |
608 if (GetNode()) { | 611 if (GetNode()) { |
609 if (GetNode()->IsInert()) { | 612 if (GetNode()->IsInert()) { |
610 if (ignored_reasons) { | 613 if (ignored_reasons) { |
611 HTMLDialogElement* dialog = GetActiveDialogElement(GetNode()); | 614 HTMLDialogElement* dialog = GetActiveDialogElement(GetNode()); |
612 if (dialog) { | 615 if (dialog) { |
613 AXObject* dialog_object = AxObjectCache().GetOrCreate(dialog); | 616 AXObjectImpl* dialog_object = AxObjectCache().GetOrCreate(dialog); |
614 if (dialog_object) | 617 if (dialog_object) { |
615 ignored_reasons->push_back( | 618 ignored_reasons->push_back( |
616 IgnoredReason(kAXActiveModalDialog, dialog_object)); | 619 IgnoredReason(kAXActiveModalDialog, dialog_object)); |
617 else | 620 } else { |
618 ignored_reasons->push_back(IgnoredReason(kAXInert)); | 621 ignored_reasons->push_back(IgnoredReason(kAXInert)); |
| 622 } |
619 } else { | 623 } else { |
620 // TODO(aboxhall): handle inert attribute if it eventuates | 624 // TODO(aboxhall): handle inert attribute if it eventuates |
621 ignored_reasons->push_back(IgnoredReason(kAXInert)); | 625 ignored_reasons->push_back(IgnoredReason(kAXInert)); |
622 } | 626 } |
623 } | 627 } |
624 return true; | 628 return true; |
625 } | 629 } |
626 } else { | 630 } else { |
627 AXObject* parent = ParentObject(); | 631 AXObjectImpl* parent = ParentObject(); |
628 if (parent && parent->IsInertOrAriaHidden()) { | 632 if (parent && parent->IsInertOrAriaHidden()) { |
629 if (ignored_reasons) | 633 if (ignored_reasons) |
630 parent->ComputeIsInertOrAriaHidden(ignored_reasons); | 634 parent->ComputeIsInertOrAriaHidden(ignored_reasons); |
631 return true; | 635 return true; |
632 } | 636 } |
633 } | 637 } |
634 | 638 |
635 const AXObject* hidden_root = AriaHiddenRoot(); | 639 const AXObjectImpl* hidden_root = AriaHiddenRoot(); |
636 if (hidden_root) { | 640 if (hidden_root) { |
637 if (ignored_reasons) { | 641 if (ignored_reasons) { |
638 if (hidden_root == this) | 642 if (hidden_root == this) { |
639 ignored_reasons->push_back(IgnoredReason(kAXAriaHidden)); | 643 ignored_reasons->push_back(IgnoredReason(kAXAriaHidden)); |
640 else | 644 } else { |
641 ignored_reasons->push_back( | 645 ignored_reasons->push_back( |
642 IgnoredReason(kAXAriaHiddenRoot, hidden_root)); | 646 IgnoredReason(kAXAriaHiddenRoot, hidden_root)); |
| 647 } |
643 } | 648 } |
644 return true; | 649 return true; |
645 } | 650 } |
646 | 651 |
647 return false; | 652 return false; |
648 } | 653 } |
649 | 654 |
650 bool AXObject::IsDescendantOfLeafNode() const { | 655 bool AXObjectImpl::IsDescendantOfLeafNode() const { |
651 UpdateCachedAttributeValuesIfNeeded(); | 656 UpdateCachedAttributeValuesIfNeeded(); |
652 return cached_is_descendant_of_leaf_node_; | 657 return cached_is_descendant_of_leaf_node_; |
653 } | 658 } |
654 | 659 |
655 AXObject* AXObject::LeafNodeAncestor() const { | 660 AXObjectImpl* AXObjectImpl::LeafNodeAncestor() const { |
656 if (AXObject* parent = ParentObject()) { | 661 if (AXObjectImpl* parent = ParentObject()) { |
657 if (!parent->CanHaveChildren()) | 662 if (!parent->CanHaveChildren()) |
658 return parent; | 663 return parent; |
659 | 664 |
660 return parent->LeafNodeAncestor(); | 665 return parent->LeafNodeAncestor(); |
661 } | 666 } |
662 | 667 |
663 return 0; | 668 return 0; |
664 } | 669 } |
665 | 670 |
666 const AXObject* AXObject::AriaHiddenRoot() const { | 671 const AXObjectImpl* AXObjectImpl::AriaHiddenRoot() const { |
667 for (const AXObject* object = this; object; object = object->ParentObject()) { | 672 for (const AXObjectImpl* object = this; object; |
| 673 object = object->ParentObject()) { |
668 if (EqualIgnoringASCIICase(object->GetAttribute(aria_hiddenAttr), "true")) | 674 if (EqualIgnoringASCIICase(object->GetAttribute(aria_hiddenAttr), "true")) |
669 return object; | 675 return object; |
670 } | 676 } |
671 | 677 |
672 return 0; | 678 return 0; |
673 } | 679 } |
674 | 680 |
675 bool AXObject::IsDescendantOfDisabledNode() const { | 681 bool AXObjectImpl::IsDescendantOfDisabledNode() const { |
676 UpdateCachedAttributeValuesIfNeeded(); | 682 UpdateCachedAttributeValuesIfNeeded(); |
677 return cached_is_descendant_of_disabled_node_; | 683 return cached_is_descendant_of_disabled_node_; |
678 } | 684 } |
679 | 685 |
680 const AXObject* AXObject::DisabledAncestor() const { | 686 const AXObjectImpl* AXObjectImpl::DisabledAncestor() const { |
681 const AtomicString& disabled = GetAttribute(aria_disabledAttr); | 687 const AtomicString& disabled = GetAttribute(aria_disabledAttr); |
682 if (EqualIgnoringASCIICase(disabled, "true")) | 688 if (EqualIgnoringASCIICase(disabled, "true")) |
683 return this; | 689 return this; |
684 if (EqualIgnoringASCIICase(disabled, "false")) | 690 if (EqualIgnoringASCIICase(disabled, "false")) |
685 return 0; | 691 return 0; |
686 | 692 |
687 if (AXObject* parent = ParentObject()) | 693 if (AXObjectImpl* parent = ParentObject()) |
688 return parent->DisabledAncestor(); | 694 return parent->DisabledAncestor(); |
689 | 695 |
690 return 0; | 696 return 0; |
691 } | 697 } |
692 | 698 |
693 bool AXObject::LastKnownIsIgnoredValue() { | 699 bool AXObjectImpl::LastKnownIsIgnoredValue() { |
694 if (last_known_is_ignored_value_ == kDefaultBehavior) | 700 if (last_known_is_ignored_value_ == kDefaultBehavior) { |
695 last_known_is_ignored_value_ = | 701 last_known_is_ignored_value_ = |
696 AccessibilityIsIgnored() ? kIgnoreObject : kIncludeObject; | 702 AccessibilityIsIgnored() ? kIgnoreObject : kIncludeObject; |
| 703 } |
697 | 704 |
698 return last_known_is_ignored_value_ == kIgnoreObject; | 705 return last_known_is_ignored_value_ == kIgnoreObject; |
699 } | 706 } |
700 | 707 |
701 void AXObject::SetLastKnownIsIgnoredValue(bool is_ignored) { | 708 void AXObjectImpl::SetLastKnownIsIgnoredValue(bool is_ignored) { |
702 last_known_is_ignored_value_ = is_ignored ? kIgnoreObject : kIncludeObject; | 709 last_known_is_ignored_value_ = is_ignored ? kIgnoreObject : kIncludeObject; |
703 } | 710 } |
704 | 711 |
705 bool AXObject::HasInheritedPresentationalRole() const { | 712 bool AXObjectImpl::HasInheritedPresentationalRole() const { |
706 UpdateCachedAttributeValuesIfNeeded(); | 713 UpdateCachedAttributeValuesIfNeeded(); |
707 return cached_has_inherited_presentational_role_; | 714 return cached_has_inherited_presentational_role_; |
708 } | 715 } |
709 | 716 |
710 bool AXObject::IsPresentationalChild() const { | 717 bool AXObjectImpl::IsPresentationalChild() const { |
711 UpdateCachedAttributeValuesIfNeeded(); | 718 UpdateCachedAttributeValuesIfNeeded(); |
712 return cached_is_presentational_child_; | 719 return cached_is_presentational_child_; |
713 } | 720 } |
714 | 721 |
715 bool AXObject::AncestorExposesActiveDescendant() const { | 722 bool AXObjectImpl::AncestorExposesActiveDescendant() const { |
716 UpdateCachedAttributeValuesIfNeeded(); | 723 UpdateCachedAttributeValuesIfNeeded(); |
717 return cached_ancestor_exposes_active_descendant_; | 724 return cached_ancestor_exposes_active_descendant_; |
718 } | 725 } |
719 | 726 |
720 bool AXObject::ComputeAncestorExposesActiveDescendant() const { | 727 bool AXObjectImpl::ComputeAncestorExposesActiveDescendant() const { |
721 const AXObject* parent = ParentObjectUnignored(); | 728 const AXObjectImpl* parent = ParentObjectUnignored(); |
722 if (!parent) | 729 if (!parent) |
723 return false; | 730 return false; |
724 | 731 |
725 if (parent->SupportsActiveDescendant() && | 732 if (parent->SupportsActiveDescendant() && |
726 !parent->GetAttribute(aria_activedescendantAttr).IsEmpty()) { | 733 !parent->GetAttribute(aria_activedescendantAttr).IsEmpty()) { |
727 return true; | 734 return true; |
728 } | 735 } |
729 | 736 |
730 return parent->AncestorExposesActiveDescendant(); | 737 return parent->AncestorExposesActiveDescendant(); |
731 } | 738 } |
732 | 739 |
733 // Simplify whitespace, but preserve a single leading and trailing whitespace | 740 // Simplify whitespace, but preserve a single leading and trailing whitespace |
734 // character if it's present. | 741 // character if it's present. |
735 // static | 742 // static |
736 String AXObject::CollapseWhitespace(const String& str) { | 743 String AXObjectImpl::CollapseWhitespace(const String& str) { |
737 StringBuilder result; | 744 StringBuilder result; |
738 if (!str.IsEmpty() && IsHTMLSpace<UChar>(str[0])) | 745 if (!str.IsEmpty() && IsHTMLSpace<UChar>(str[0])) |
739 result.Append(' '); | 746 result.Append(' '); |
740 result.Append(str.SimplifyWhiteSpace(IsHTMLSpace<UChar>)); | 747 result.Append(str.SimplifyWhiteSpace(IsHTMLSpace<UChar>)); |
741 if (!str.IsEmpty() && IsHTMLSpace<UChar>(str[str.length() - 1])) | 748 if (!str.IsEmpty() && IsHTMLSpace<UChar>(str[str.length() - 1])) |
742 result.Append(' '); | 749 result.Append(' '); |
743 return result.ToString(); | 750 return result.ToString(); |
744 } | 751 } |
745 | 752 |
746 String AXObject::ComputedName() const { | 753 String AXObjectImpl::ComputedName() const { |
747 AXNameFrom name_from; | 754 AXNameFrom name_from; |
748 AXObject::AXObjectVector name_objects; | 755 AXObjectImpl::AXObjectVector name_objects; |
749 return GetName(name_from, &name_objects); | 756 return GetName(name_from, &name_objects); |
750 } | 757 } |
751 | 758 |
752 String AXObject::GetName(AXNameFrom& name_from, | 759 String AXObjectImpl::GetName(AXNameFrom& name_from, |
753 AXObject::AXObjectVector* name_objects) const { | 760 AXObjectImpl::AXObjectVector* name_objects) const { |
754 HeapHashSet<Member<const AXObject>> visited; | 761 HeapHashSet<Member<const AXObjectImpl>> visited; |
755 AXRelatedObjectVector related_objects; | 762 AXRelatedObjectVector related_objects; |
756 String text = TextAlternative(false, false, visited, name_from, | 763 String text = TextAlternative(false, false, visited, name_from, |
757 &related_objects, nullptr); | 764 &related_objects, nullptr); |
758 | 765 |
759 AccessibilityRole role = RoleValue(); | 766 AccessibilityRole role = RoleValue(); |
760 if (!GetNode() || (!isHTMLBRElement(GetNode()) && role != kStaticTextRole && | 767 if (!GetNode() || (!isHTMLBRElement(GetNode()) && role != kStaticTextRole && |
761 role != kInlineTextBoxRole)) | 768 role != kInlineTextBoxRole)) |
762 text = CollapseWhitespace(text); | 769 text = CollapseWhitespace(text); |
763 | 770 |
764 if (name_objects) { | 771 if (name_objects) { |
765 name_objects->clear(); | 772 name_objects->clear(); |
766 for (size_t i = 0; i < related_objects.size(); i++) | 773 for (size_t i = 0; i < related_objects.size(); i++) |
767 name_objects->push_back(related_objects[i]->object); | 774 name_objects->push_back(related_objects[i]->object); |
768 } | 775 } |
769 | 776 |
770 return text; | 777 return text; |
771 } | 778 } |
772 | 779 |
773 String AXObject::GetName(NameSources* name_sources) const { | 780 String AXObjectImpl::GetName(NameSources* name_sources) const { |
774 AXObjectSet visited; | 781 AXObjectSet visited; |
775 AXNameFrom tmp_name_from; | 782 AXNameFrom tmp_name_from; |
776 AXRelatedObjectVector tmp_related_objects; | 783 AXRelatedObjectVector tmp_related_objects; |
777 String text = TextAlternative(false, false, visited, tmp_name_from, | 784 String text = TextAlternative(false, false, visited, tmp_name_from, |
778 &tmp_related_objects, name_sources); | 785 &tmp_related_objects, name_sources); |
779 text = text.SimplifyWhiteSpace(IsHTMLSpace<UChar>); | 786 text = text.SimplifyWhiteSpace(IsHTMLSpace<UChar>); |
780 return text; | 787 return text; |
781 } | 788 } |
782 | 789 |
783 String AXObject::RecursiveTextAlternative(const AXObject& ax_obj, | 790 String AXObjectImpl::RecursiveTextAlternative( |
784 bool in_aria_labelled_by_traversal, | 791 const AXObjectImpl& ax_obj, |
785 AXObjectSet& visited) { | 792 bool in_aria_labelled_by_traversal, |
| 793 AXObjectSet& visited) { |
786 if (visited.Contains(&ax_obj) && !in_aria_labelled_by_traversal) | 794 if (visited.Contains(&ax_obj) && !in_aria_labelled_by_traversal) |
787 return String(); | 795 return String(); |
788 | 796 |
789 AXNameFrom tmp_name_from; | 797 AXNameFrom tmp_name_from; |
790 return ax_obj.TextAlternative(true, in_aria_labelled_by_traversal, visited, | 798 return ax_obj.TextAlternative(true, in_aria_labelled_by_traversal, visited, |
791 tmp_name_from, nullptr, nullptr); | 799 tmp_name_from, nullptr, nullptr); |
792 } | 800 } |
793 | 801 |
794 bool AXObject::IsHiddenForTextAlternativeCalculation() const { | 802 bool AXObjectImpl::IsHiddenForTextAlternativeCalculation() const { |
795 if (EqualIgnoringASCIICase(GetAttribute(aria_hiddenAttr), "false")) | 803 if (EqualIgnoringASCIICase(GetAttribute(aria_hiddenAttr), "false")) |
796 return false; | 804 return false; |
797 | 805 |
798 if (GetLayoutObject()) | 806 if (GetLayoutObject()) |
799 return GetLayoutObject()->Style()->Visibility() != EVisibility::kVisible; | 807 return GetLayoutObject()->Style()->Visibility() != EVisibility::kVisible; |
800 | 808 |
801 // This is an obscure corner case: if a node has no LayoutObject, that means | 809 // This is an obscure corner case: if a node has no LayoutObject, that means |
802 // it's not rendered, but we still may be exploring it as part of a text | 810 // it's not rendered, but we still may be exploring it as part of a text |
803 // alternative calculation, for example if it was explicitly referenced by | 811 // alternative calculation, for example if it was explicitly referenced by |
804 // aria-labelledby. So we need to explicitly call the style resolver to check | 812 // aria-labelledby. So we need to explicitly call the style resolver to check |
805 // whether it's invisible or display:none, rather than relying on the style | 813 // whether it's invisible or display:none, rather than relying on the style |
806 // cached in the LayoutObject. | 814 // cached in the LayoutObject. |
807 Document* document = GetDocument(); | 815 Document* document = GetDocument(); |
808 if (!document || !document->GetFrame()) | 816 if (!document || !document->GetFrame()) |
809 return false; | 817 return false; |
810 if (Node* node = GetNode()) { | 818 if (Node* node = GetNode()) { |
811 if (node->isConnected() && node->IsElementNode()) { | 819 if (node->isConnected() && node->IsElementNode()) { |
812 RefPtr<ComputedStyle> style = | 820 RefPtr<ComputedStyle> style = |
813 document->EnsureStyleResolver().StyleForElement(ToElement(node)); | 821 document->EnsureStyleResolver().StyleForElement(ToElement(node)); |
814 return style->Display() == EDisplay::kNone || | 822 return style->Display() == EDisplay::kNone || |
815 style->Visibility() != EVisibility::kVisible; | 823 style->Visibility() != EVisibility::kVisible; |
816 } | 824 } |
817 } | 825 } |
818 return false; | 826 return false; |
819 } | 827 } |
820 | 828 |
821 String AXObject::AriaTextAlternative(bool recursive, | 829 String AXObjectImpl::AriaTextAlternative(bool recursive, |
822 bool in_aria_labelled_by_traversal, | 830 bool in_aria_labelled_by_traversal, |
823 AXObjectSet& visited, | 831 AXObjectSet& visited, |
824 AXNameFrom& name_from, | 832 AXNameFrom& name_from, |
825 AXRelatedObjectVector* related_objects, | 833 AXRelatedObjectVector* related_objects, |
826 NameSources* name_sources, | 834 NameSources* name_sources, |
827 bool* found_text_alternative) const { | 835 bool* found_text_alternative) const { |
828 String text_alternative; | 836 String text_alternative; |
829 bool already_visited = visited.Contains(this); | 837 bool already_visited = visited.Contains(this); |
830 visited.insert(this); | 838 visited.insert(this); |
831 | 839 |
832 // Step 2A from: http://www.w3.org/TR/accname-aam-1.1 | 840 // Step 2A from: http://www.w3.org/TR/accname-aam-1.1 |
833 // If you change this logic, update AXNodeObject::nameFromLabelElement, too. | 841 // If you change this logic, update AXNodeObject::nameFromLabelElement, too. |
834 if (!in_aria_labelled_by_traversal && | 842 if (!in_aria_labelled_by_traversal && |
835 IsHiddenForTextAlternativeCalculation()) { | 843 IsHiddenForTextAlternativeCalculation()) { |
836 *found_text_alternative = true; | 844 *found_text_alternative = true; |
837 return String(); | 845 return String(); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 *found_text_alternative = true; | 905 *found_text_alternative = true; |
898 } else { | 906 } else { |
899 *found_text_alternative = true; | 907 *found_text_alternative = true; |
900 return text_alternative; | 908 return text_alternative; |
901 } | 909 } |
902 } | 910 } |
903 | 911 |
904 return text_alternative; | 912 return text_alternative; |
905 } | 913 } |
906 | 914 |
907 String AXObject::TextFromElements( | 915 String AXObjectImpl::TextFromElements( |
908 bool in_aria_labelledby_traversal, | 916 bool in_aria_labelledby_traversal, |
909 AXObjectSet& visited, | 917 AXObjectSet& visited, |
910 HeapVector<Member<Element>>& elements, | 918 HeapVector<Member<Element>>& elements, |
911 AXRelatedObjectVector* related_objects) const { | 919 AXRelatedObjectVector* related_objects) const { |
912 StringBuilder accumulated_text; | 920 StringBuilder accumulated_text; |
913 bool found_valid_element = false; | 921 bool found_valid_element = false; |
914 AXRelatedObjectVector local_related_objects; | 922 AXRelatedObjectVector local_related_objects; |
915 | 923 |
916 for (const auto& element : elements) { | 924 for (const auto& element : elements) { |
917 AXObject* ax_element = AxObjectCache().GetOrCreate(element); | 925 AXObjectImpl* ax_element = AxObjectCache().GetOrCreate(element); |
918 if (ax_element) { | 926 if (ax_element) { |
919 found_valid_element = true; | 927 found_valid_element = true; |
920 | 928 |
921 String result = RecursiveTextAlternative( | 929 String result = RecursiveTextAlternative( |
922 *ax_element, in_aria_labelledby_traversal, visited); | 930 *ax_element, in_aria_labelledby_traversal, visited); |
923 local_related_objects.push_back( | 931 local_related_objects.push_back( |
924 new NameSourceRelatedObject(ax_element, result)); | 932 new NameSourceRelatedObject(ax_element, result)); |
925 if (!result.IsEmpty()) { | 933 if (!result.IsEmpty()) { |
926 if (!accumulated_text.IsEmpty()) | 934 if (!accumulated_text.IsEmpty()) |
927 accumulated_text.Append(' '); | 935 accumulated_text.Append(' '); |
928 accumulated_text.Append(result); | 936 accumulated_text.Append(result); |
929 } | 937 } |
930 } | 938 } |
931 } | 939 } |
932 if (!found_valid_element) | 940 if (!found_valid_element) |
933 return String(); | 941 return String(); |
934 if (related_objects) | 942 if (related_objects) |
935 *related_objects = local_related_objects; | 943 *related_objects = local_related_objects; |
936 return accumulated_text.ToString(); | 944 return accumulated_text.ToString(); |
937 } | 945 } |
938 | 946 |
939 void AXObject::TokenVectorFromAttribute(Vector<String>& tokens, | 947 void AXObjectImpl::TokenVectorFromAttribute( |
940 const QualifiedName& attribute) const { | 948 Vector<String>& tokens, |
| 949 const QualifiedName& attribute) const { |
941 Node* node = this->GetNode(); | 950 Node* node = this->GetNode(); |
942 if (!node || !node->IsElementNode()) | 951 if (!node || !node->IsElementNode()) |
943 return; | 952 return; |
944 | 953 |
945 String attribute_value = GetAttribute(attribute).GetString(); | 954 String attribute_value = GetAttribute(attribute).GetString(); |
946 if (attribute_value.IsEmpty()) | 955 if (attribute_value.IsEmpty()) |
947 return; | 956 return; |
948 | 957 |
949 attribute_value.SimplifyWhiteSpace(); | 958 attribute_value.SimplifyWhiteSpace(); |
950 attribute_value.Split(' ', tokens); | 959 attribute_value.Split(' ', tokens); |
951 } | 960 } |
952 | 961 |
953 void AXObject::ElementsFromAttribute(HeapVector<Member<Element>>& elements, | 962 void AXObjectImpl::ElementsFromAttribute(HeapVector<Member<Element>>& elements, |
954 const QualifiedName& attribute) const { | 963 const QualifiedName& attribute) const { |
955 Vector<String> ids; | 964 Vector<String> ids; |
956 TokenVectorFromAttribute(ids, attribute); | 965 TokenVectorFromAttribute(ids, attribute); |
957 if (ids.IsEmpty()) | 966 if (ids.IsEmpty()) |
958 return; | 967 return; |
959 | 968 |
960 TreeScope& scope = GetNode()->GetTreeScope(); | 969 TreeScope& scope = GetNode()->GetTreeScope(); |
961 for (const auto& id : ids) { | 970 for (const auto& id : ids) { |
962 if (Element* id_element = scope.getElementById(AtomicString(id))) | 971 if (Element* id_element = scope.getElementById(AtomicString(id))) |
963 elements.push_back(id_element); | 972 elements.push_back(id_element); |
964 } | 973 } |
965 } | 974 } |
966 | 975 |
967 void AXObject::AriaLabelledbyElementVector( | 976 void AXObjectImpl::AriaLabelledbyElementVector( |
968 HeapVector<Member<Element>>& elements) const { | 977 HeapVector<Member<Element>>& elements) const { |
969 // Try both spellings, but prefer aria-labelledby, which is the official spec. | 978 // Try both spellings, but prefer aria-labelledby, which is the official spec. |
970 ElementsFromAttribute(elements, aria_labelledbyAttr); | 979 ElementsFromAttribute(elements, aria_labelledbyAttr); |
971 if (!elements.size()) | 980 if (!elements.size()) |
972 ElementsFromAttribute(elements, aria_labeledbyAttr); | 981 ElementsFromAttribute(elements, aria_labeledbyAttr); |
973 } | 982 } |
974 | 983 |
975 String AXObject::TextFromAriaLabelledby( | 984 String AXObjectImpl::TextFromAriaLabelledby( |
976 AXObjectSet& visited, | 985 AXObjectSet& visited, |
977 AXRelatedObjectVector* related_objects) const { | 986 AXRelatedObjectVector* related_objects) const { |
978 HeapVector<Member<Element>> elements; | 987 HeapVector<Member<Element>> elements; |
979 AriaLabelledbyElementVector(elements); | 988 AriaLabelledbyElementVector(elements); |
980 return TextFromElements(true, visited, elements, related_objects); | 989 return TextFromElements(true, visited, elements, related_objects); |
981 } | 990 } |
982 | 991 |
983 String AXObject::TextFromAriaDescribedby( | 992 String AXObjectImpl::TextFromAriaDescribedby( |
984 AXRelatedObjectVector* related_objects) const { | 993 AXRelatedObjectVector* related_objects) const { |
985 AXObjectSet visited; | 994 AXObjectSet visited; |
986 HeapVector<Member<Element>> elements; | 995 HeapVector<Member<Element>> elements; |
987 ElementsFromAttribute(elements, aria_describedbyAttr); | 996 ElementsFromAttribute(elements, aria_describedbyAttr); |
988 return TextFromElements(true, visited, elements, related_objects); | 997 return TextFromElements(true, visited, elements, related_objects); |
989 } | 998 } |
990 | 999 |
991 RGBA32 AXObject::BackgroundColor() const { | 1000 RGBA32 AXObjectImpl::BackgroundColor() const { |
992 UpdateCachedAttributeValuesIfNeeded(); | 1001 UpdateCachedAttributeValuesIfNeeded(); |
993 return cached_background_color_; | 1002 return cached_background_color_; |
994 } | 1003 } |
995 | 1004 |
996 AccessibilityOrientation AXObject::Orientation() const { | 1005 AccessibilityOrientation AXObjectImpl::Orientation() const { |
997 // In ARIA 1.1, the default value for aria-orientation changed from | 1006 // In ARIA 1.1, the default value for aria-orientation changed from |
998 // horizontal to undefined. | 1007 // horizontal to undefined. |
999 return kAccessibilityOrientationUndefined; | 1008 return kAccessibilityOrientationUndefined; |
1000 } | 1009 } |
1001 | 1010 |
1002 AXSupportedAction AXObject::Action() const { | 1011 AXSupportedAction AXObjectImpl::Action() const { |
1003 if (!ActionElement()) | 1012 if (!ActionElement()) |
1004 return AXSupportedAction::kNone; | 1013 return AXSupportedAction::kNone; |
1005 | 1014 |
1006 switch (RoleValue()) { | 1015 switch (RoleValue()) { |
1007 case kButtonRole: | 1016 case kButtonRole: |
1008 case kToggleButtonRole: | 1017 case kToggleButtonRole: |
1009 return AXSupportedAction::kPress; | 1018 return AXSupportedAction::kPress; |
1010 case kTextFieldRole: | 1019 case kTextFieldRole: |
1011 return AXSupportedAction::kActivate; | 1020 return AXSupportedAction::kActivate; |
1012 case kRadioButtonRole: | 1021 case kRadioButtonRole: |
1013 return AXSupportedAction::kSelect; | 1022 return AXSupportedAction::kSelect; |
1014 case kCheckBoxRole: | 1023 case kCheckBoxRole: |
1015 case kSwitchRole: | 1024 case kSwitchRole: |
1016 return CheckedState() == kButtonStateOff ? AXSupportedAction::kCheck | 1025 return CheckedState() == kButtonStateOff ? AXSupportedAction::kCheck |
1017 : AXSupportedAction::kUncheck; | 1026 : AXSupportedAction::kUncheck; |
1018 case kLinkRole: | 1027 case kLinkRole: |
1019 return AXSupportedAction::kJump; | 1028 return AXSupportedAction::kJump; |
1020 case kPopUpButtonRole: | 1029 case kPopUpButtonRole: |
1021 return AXSupportedAction::kOpen; | 1030 return AXSupportedAction::kOpen; |
1022 default: | 1031 default: |
1023 return AXSupportedAction::kClick; | 1032 return AXSupportedAction::kClick; |
1024 } | 1033 } |
1025 } | 1034 } |
1026 | 1035 |
1027 bool AXObject::IsMultiline() const { | 1036 bool AXObjectImpl::IsMultiline() const { |
1028 Node* node = this->GetNode(); | 1037 Node* node = this->GetNode(); |
1029 if (!node) | 1038 if (!node) |
1030 return false; | 1039 return false; |
1031 | 1040 |
1032 if (isHTMLTextAreaElement(*node)) | 1041 if (isHTMLTextAreaElement(*node)) |
1033 return true; | 1042 return true; |
1034 | 1043 |
1035 if (HasEditableStyle(*node)) | 1044 if (HasEditableStyle(*node)) |
1036 return true; | 1045 return true; |
1037 | 1046 |
1038 if (!IsNativeTextControl() && !IsNonNativeTextControl()) | 1047 if (!IsNativeTextControl() && !IsNonNativeTextControl()) |
1039 return false; | 1048 return false; |
1040 | 1049 |
1041 return EqualIgnoringASCIICase(GetAttribute(aria_multilineAttr), "true"); | 1050 return EqualIgnoringASCIICase(GetAttribute(aria_multilineAttr), "true"); |
1042 } | 1051 } |
1043 | 1052 |
1044 bool AXObject::AriaPressedIsPresent() const { | 1053 bool AXObjectImpl::AriaPressedIsPresent() const { |
1045 return !GetAttribute(aria_pressedAttr).IsEmpty(); | 1054 return !GetAttribute(aria_pressedAttr).IsEmpty(); |
1046 } | 1055 } |
1047 | 1056 |
1048 bool AXObject::SupportsActiveDescendant() const { | 1057 bool AXObjectImpl::SupportsActiveDescendant() const { |
1049 // According to the ARIA Spec, all ARIA composite widgets, ARIA text boxes | 1058 // According to the ARIA Spec, all ARIA composite widgets, ARIA text boxes |
1050 // and ARIA groups should be able to expose an active descendant. | 1059 // and ARIA groups should be able to expose an active descendant. |
1051 // Implicitly, <input> and <textarea> elements should also have this ability. | 1060 // Implicitly, <input> and <textarea> elements should also have this ability. |
1052 switch (AriaRoleAttribute()) { | 1061 switch (AriaRoleAttribute()) { |
1053 case kComboBoxRole: | 1062 case kComboBoxRole: |
1054 case kGridRole: | 1063 case kGridRole: |
1055 case kGroupRole: | 1064 case kGroupRole: |
1056 case kListBoxRole: | 1065 case kListBoxRole: |
1057 case kMenuRole: | 1066 case kMenuRole: |
1058 case kMenuBarRole: | 1067 case kMenuBarRole: |
1059 case kRadioGroupRole: | 1068 case kRadioGroupRole: |
1060 case kRowRole: | 1069 case kRowRole: |
1061 case kSearchBoxRole: | 1070 case kSearchBoxRole: |
1062 case kTabListRole: | 1071 case kTabListRole: |
1063 case kTextFieldRole: | 1072 case kTextFieldRole: |
1064 case kToolbarRole: | 1073 case kToolbarRole: |
1065 case kTreeRole: | 1074 case kTreeRole: |
1066 case kTreeGridRole: | 1075 case kTreeGridRole: |
1067 return true; | 1076 return true; |
1068 default: | 1077 default: |
1069 return false; | 1078 return false; |
1070 } | 1079 } |
1071 } | 1080 } |
1072 | 1081 |
1073 bool AXObject::SupportsARIAAttributes() const { | 1082 bool AXObjectImpl::SupportsARIAAttributes() const { |
1074 return IsLiveRegion() || SupportsARIADragging() || SupportsARIADropping() || | 1083 return IsLiveRegion() || SupportsARIADragging() || SupportsARIADropping() || |
1075 SupportsARIAFlowTo() || SupportsARIAOwns() || | 1084 SupportsARIAFlowTo() || SupportsARIAOwns() || |
1076 HasAttribute(aria_labelAttr); | 1085 HasAttribute(aria_labelAttr); |
1077 } | 1086 } |
1078 | 1087 |
1079 bool AXObject::SupportsRangeValue() const { | 1088 bool AXObjectImpl::SupportsRangeValue() const { |
1080 return IsProgressIndicator() || IsMeter() || IsSlider() || IsScrollbar() || | 1089 return IsProgressIndicator() || IsMeter() || IsSlider() || IsScrollbar() || |
1081 IsSpinButton(); | 1090 IsSpinButton(); |
1082 } | 1091 } |
1083 | 1092 |
1084 bool AXObject::SupportsSetSizeAndPosInSet() const { | 1093 bool AXObjectImpl::SupportsSetSizeAndPosInSet() const { |
1085 AXObject* parent = ParentObject(); | 1094 AXObjectImpl* parent = ParentObject(); |
1086 if (!parent) | 1095 if (!parent) |
1087 return false; | 1096 return false; |
1088 | 1097 |
1089 int role = RoleValue(); | 1098 int role = RoleValue(); |
1090 int parent_role = parent->RoleValue(); | 1099 int parent_role = parent->RoleValue(); |
1091 | 1100 |
1092 if ((role == kListBoxOptionRole && parent_role == kListBoxRole) || | 1101 if ((role == kListBoxOptionRole && parent_role == kListBoxRole) || |
1093 (role == kListItemRole && parent_role == kListRole) || | 1102 (role == kListItemRole && parent_role == kListRole) || |
1094 (role == kMenuItemRole && parent_role == kMenuRole) || | 1103 (role == kMenuItemRole && parent_role == kMenuRole) || |
1095 (role == kRadioButtonRole) || | 1104 (role == kRadioButtonRole) || |
1096 (role == kTabRole && parent_role == kTabListRole) || | 1105 (role == kTabRole && parent_role == kTabListRole) || |
1097 (role == kTreeItemRole && parent_role == kTreeRole) || | 1106 (role == kTreeItemRole && parent_role == kTreeRole) || |
1098 (role == kTreeItemRole && parent_role == kGroupRole)) { | 1107 (role == kTreeItemRole && parent_role == kGroupRole)) { |
1099 return true; | 1108 return true; |
1100 } | 1109 } |
1101 | 1110 |
1102 return false; | 1111 return false; |
1103 } | 1112 } |
1104 | 1113 |
1105 int AXObject::IndexInParent() const { | 1114 int AXObjectImpl::IndexInParent() const { |
1106 if (!ParentObject()) | 1115 if (!ParentObject()) |
1107 return 0; | 1116 return 0; |
1108 | 1117 |
1109 const auto& siblings = ParentObject()->Children(); | 1118 const auto& siblings = ParentObject()->Children(); |
1110 int child_count = siblings.size(); | 1119 int child_count = siblings.size(); |
1111 | 1120 |
1112 for (int index = 0; index < child_count; ++index) { | 1121 for (int index = 0; index < child_count; ++index) { |
1113 if (siblings[index].Get() == this) { | 1122 if (siblings[index].Get() == this) { |
1114 return index; | 1123 return index; |
1115 } | 1124 } |
1116 } | 1125 } |
1117 return 0; | 1126 return 0; |
1118 } | 1127 } |
1119 | 1128 |
1120 bool AXObject::IsLiveRegion() const { | 1129 bool AXObjectImpl::IsLiveRegion() const { |
1121 const AtomicString& live_region = LiveRegionStatus(); | 1130 const AtomicString& live_region = LiveRegionStatus(); |
1122 return EqualIgnoringASCIICase(live_region, "polite") || | 1131 return EqualIgnoringASCIICase(live_region, "polite") || |
1123 EqualIgnoringASCIICase(live_region, "assertive"); | 1132 EqualIgnoringASCIICase(live_region, "assertive"); |
1124 } | 1133 } |
1125 | 1134 |
1126 AXObject* AXObject::LiveRegionRoot() const { | 1135 AXObjectImpl* AXObjectImpl::LiveRegionRoot() const { |
1127 UpdateCachedAttributeValuesIfNeeded(); | 1136 UpdateCachedAttributeValuesIfNeeded(); |
1128 return cached_live_region_root_; | 1137 return cached_live_region_root_; |
1129 } | 1138 } |
1130 | 1139 |
1131 const AtomicString& AXObject::ContainerLiveRegionStatus() const { | 1140 const AtomicString& AXObjectImpl::ContainerLiveRegionStatus() const { |
1132 UpdateCachedAttributeValuesIfNeeded(); | 1141 UpdateCachedAttributeValuesIfNeeded(); |
1133 return cached_live_region_root_ ? cached_live_region_root_->LiveRegionStatus() | 1142 return cached_live_region_root_ ? cached_live_region_root_->LiveRegionStatus() |
1134 : g_null_atom; | 1143 : g_null_atom; |
1135 } | 1144 } |
1136 | 1145 |
1137 const AtomicString& AXObject::ContainerLiveRegionRelevant() const { | 1146 const AtomicString& AXObjectImpl::ContainerLiveRegionRelevant() const { |
1138 UpdateCachedAttributeValuesIfNeeded(); | 1147 UpdateCachedAttributeValuesIfNeeded(); |
1139 return cached_live_region_root_ | 1148 return cached_live_region_root_ |
1140 ? cached_live_region_root_->LiveRegionRelevant() | 1149 ? cached_live_region_root_->LiveRegionRelevant() |
1141 : g_null_atom; | 1150 : g_null_atom; |
1142 } | 1151 } |
1143 | 1152 |
1144 bool AXObject::ContainerLiveRegionAtomic() const { | 1153 bool AXObjectImpl::ContainerLiveRegionAtomic() const { |
1145 UpdateCachedAttributeValuesIfNeeded(); | 1154 UpdateCachedAttributeValuesIfNeeded(); |
1146 return cached_live_region_root_ && | 1155 return cached_live_region_root_ && |
1147 cached_live_region_root_->LiveRegionAtomic(); | 1156 cached_live_region_root_->LiveRegionAtomic(); |
1148 } | 1157 } |
1149 | 1158 |
1150 bool AXObject::ContainerLiveRegionBusy() const { | 1159 bool AXObjectImpl::ContainerLiveRegionBusy() const { |
1151 UpdateCachedAttributeValuesIfNeeded(); | 1160 UpdateCachedAttributeValuesIfNeeded(); |
1152 return cached_live_region_root_ && cached_live_region_root_->LiveRegionBusy(); | 1161 return cached_live_region_root_ && cached_live_region_root_->LiveRegionBusy(); |
1153 } | 1162 } |
1154 | 1163 |
1155 AXObject* AXObject::ElementAccessibilityHitTest(const IntPoint& point) const { | 1164 AXObjectImpl* AXObjectImpl::ElementAccessibilityHitTest( |
| 1165 const IntPoint& point) const { |
1156 // Check if there are any mock elements that need to be handled. | 1166 // Check if there are any mock elements that need to be handled. |
1157 for (const auto& child : children_) { | 1167 for (const auto& child : children_) { |
1158 if (child->IsMockObject() && | 1168 if (child->IsMockObject() && |
1159 child->GetBoundsInFrameCoordinates().Contains(point)) | 1169 child->GetBoundsInFrameCoordinates().Contains(point)) |
1160 return child->ElementAccessibilityHitTest(point); | 1170 return child->ElementAccessibilityHitTest(point); |
1161 } | 1171 } |
1162 | 1172 |
1163 return const_cast<AXObject*>(this); | 1173 return const_cast<AXObjectImpl*>(this); |
1164 } | 1174 } |
1165 | 1175 |
1166 const AXObject::AXObjectVector& AXObject::Children() { | 1176 const AXObjectImpl::AXObjectVector& AXObjectImpl::Children() { |
1167 UpdateChildrenIfNecessary(); | 1177 UpdateChildrenIfNecessary(); |
1168 | 1178 |
1169 return children_; | 1179 return children_; |
1170 } | 1180 } |
1171 | 1181 |
1172 AXObject* AXObject::ParentObject() const { | 1182 AXObjectImpl* AXObjectImpl::ParentObject() const { |
1173 if (IsDetached()) | 1183 if (IsDetached()) |
1174 return 0; | 1184 return 0; |
1175 | 1185 |
1176 if (parent_) | 1186 if (parent_) |
1177 return parent_; | 1187 return parent_; |
1178 | 1188 |
1179 if (AxObjectCache().IsAriaOwned(this)) | 1189 if (AxObjectCache().IsAriaOwned(this)) |
1180 return AxObjectCache().GetAriaOwnedParent(this); | 1190 return AxObjectCache().GetAriaOwnedParent(this); |
1181 | 1191 |
1182 return ComputeParent(); | 1192 return ComputeParent(); |
1183 } | 1193 } |
1184 | 1194 |
1185 AXObject* AXObject::ParentObjectIfExists() const { | 1195 AXObjectImpl* AXObjectImpl::ParentObjectIfExists() const { |
1186 if (IsDetached()) | 1196 if (IsDetached()) |
1187 return 0; | 1197 return 0; |
1188 | 1198 |
1189 if (parent_) | 1199 if (parent_) |
1190 return parent_; | 1200 return parent_; |
1191 | 1201 |
1192 return ComputeParentIfExists(); | 1202 return ComputeParentIfExists(); |
1193 } | 1203 } |
1194 | 1204 |
1195 AXObject* AXObject::ParentObjectUnignored() const { | 1205 AXObjectImpl* AXObjectImpl::ParentObjectUnignored() const { |
1196 AXObject* parent; | 1206 AXObjectImpl* parent; |
1197 for (parent = ParentObject(); parent && parent->AccessibilityIsIgnored(); | 1207 for (parent = ParentObject(); parent && parent->AccessibilityIsIgnored(); |
1198 parent = parent->ParentObject()) { | 1208 parent = parent->ParentObject()) { |
1199 } | 1209 } |
1200 | 1210 |
1201 return parent; | 1211 return parent; |
1202 } | 1212 } |
1203 | 1213 |
1204 void AXObject::UpdateChildrenIfNecessary() { | 1214 void AXObjectImpl::UpdateChildrenIfNecessary() { |
1205 if (!HasChildren()) | 1215 if (!HasChildren()) |
1206 AddChildren(); | 1216 AddChildren(); |
1207 } | 1217 } |
1208 | 1218 |
1209 void AXObject::ClearChildren() { | 1219 void AXObjectImpl::ClearChildren() { |
1210 // Detach all weak pointers from objects to their parents. | 1220 // Detach all weak pointers from objects to their parents. |
1211 for (const auto& child : children_) | 1221 for (const auto& child : children_) |
1212 child->DetachFromParent(); | 1222 child->DetachFromParent(); |
1213 | 1223 |
1214 children_.clear(); | 1224 children_.clear(); |
1215 have_children_ = false; | 1225 have_children_ = false; |
1216 } | 1226 } |
1217 | 1227 |
1218 Document* AXObject::GetDocument() const { | 1228 Document* AXObjectImpl::GetDocument() const { |
1219 FrameView* frame_view = DocumentFrameView(); | 1229 FrameView* frame_view = DocumentFrameView(); |
1220 if (!frame_view) | 1230 if (!frame_view) |
1221 return 0; | 1231 return 0; |
1222 | 1232 |
1223 return frame_view->GetFrame().GetDocument(); | 1233 return frame_view->GetFrame().GetDocument(); |
1224 } | 1234 } |
1225 | 1235 |
1226 FrameView* AXObject::DocumentFrameView() const { | 1236 FrameView* AXObjectImpl::DocumentFrameView() const { |
1227 const AXObject* object = this; | 1237 const AXObjectImpl* object = this; |
1228 while (object && !object->IsAXLayoutObject()) | 1238 while (object && !object->IsAXLayoutObject()) |
1229 object = object->ParentObject(); | 1239 object = object->ParentObject(); |
1230 | 1240 |
1231 if (!object) | 1241 if (!object) |
1232 return 0; | 1242 return 0; |
1233 | 1243 |
1234 return object->DocumentFrameView(); | 1244 return object->DocumentFrameView(); |
1235 } | 1245 } |
1236 | 1246 |
1237 String AXObject::Language() const { | 1247 String AXObjectImpl::Language() const { |
1238 const AtomicString& lang = GetAttribute(langAttr); | 1248 const AtomicString& lang = GetAttribute(langAttr); |
1239 if (!lang.IsEmpty()) | 1249 if (!lang.IsEmpty()) |
1240 return lang; | 1250 return lang; |
1241 | 1251 |
1242 AXObject* parent = ParentObject(); | 1252 AXObjectImpl* parent = ParentObject(); |
1243 | 1253 |
1244 // As a last resort, fall back to the content language specified in the meta | 1254 // As a last resort, fall back to the content language specified in the meta |
1245 // tag. | 1255 // tag. |
1246 if (!parent) { | 1256 if (!parent) { |
1247 Document* doc = GetDocument(); | 1257 Document* doc = GetDocument(); |
1248 if (doc) | 1258 if (doc) |
1249 return doc->ContentLanguage(); | 1259 return doc->ContentLanguage(); |
1250 return g_null_atom; | 1260 return g_null_atom; |
1251 } | 1261 } |
1252 | 1262 |
1253 return parent->Language(); | 1263 return parent->Language(); |
1254 } | 1264 } |
1255 | 1265 |
1256 bool AXObject::HasAttribute(const QualifiedName& attribute) const { | 1266 bool AXObjectImpl::HasAttribute(const QualifiedName& attribute) const { |
1257 Node* element_node = GetNode(); | 1267 Node* element_node = GetNode(); |
1258 if (!element_node) | 1268 if (!element_node) |
1259 return false; | 1269 return false; |
1260 | 1270 |
1261 if (!element_node->IsElementNode()) | 1271 if (!element_node->IsElementNode()) |
1262 return false; | 1272 return false; |
1263 | 1273 |
1264 Element* element = ToElement(element_node); | 1274 Element* element = ToElement(element_node); |
1265 return element->FastHasAttribute(attribute); | 1275 return element->FastHasAttribute(attribute); |
1266 } | 1276 } |
1267 | 1277 |
1268 const AtomicString& AXObject::GetAttribute( | 1278 const AtomicString& AXObjectImpl::GetAttribute( |
1269 const QualifiedName& attribute) const { | 1279 const QualifiedName& attribute) const { |
1270 Node* element_node = GetNode(); | 1280 Node* element_node = GetNode(); |
1271 if (!element_node) | 1281 if (!element_node) |
1272 return g_null_atom; | 1282 return g_null_atom; |
1273 | 1283 |
1274 if (!element_node->IsElementNode()) | 1284 if (!element_node->IsElementNode()) |
1275 return g_null_atom; | 1285 return g_null_atom; |
1276 | 1286 |
1277 Element* element = ToElement(element_node); | 1287 Element* element = ToElement(element_node); |
1278 return element->FastGetAttribute(attribute); | 1288 return element->FastGetAttribute(attribute); |
1279 } | 1289 } |
1280 | 1290 |
1281 // | 1291 // |
1282 // Scrollable containers. | 1292 // Scrollable containers. |
1283 // | 1293 // |
1284 | 1294 |
1285 bool AXObject::IsScrollableContainer() const { | 1295 bool AXObjectImpl::IsScrollableContainer() const { |
1286 return !!GetScrollableAreaIfScrollable(); | 1296 return !!GetScrollableAreaIfScrollable(); |
1287 } | 1297 } |
1288 | 1298 |
1289 IntPoint AXObject::GetScrollOffset() const { | 1299 IntPoint AXObjectImpl::GetScrollOffset() const { |
1290 ScrollableArea* area = GetScrollableAreaIfScrollable(); | 1300 ScrollableArea* area = GetScrollableAreaIfScrollable(); |
1291 if (!area) | 1301 if (!area) |
1292 return IntPoint(); | 1302 return IntPoint(); |
1293 | 1303 |
1294 return IntPoint(area->ScrollOffsetInt().Width(), | 1304 return IntPoint(area->ScrollOffsetInt().Width(), |
1295 area->ScrollOffsetInt().Height()); | 1305 area->ScrollOffsetInt().Height()); |
1296 } | 1306 } |
1297 | 1307 |
1298 IntPoint AXObject::MinimumScrollOffset() const { | 1308 IntPoint AXObjectImpl::MinimumScrollOffset() const { |
1299 ScrollableArea* area = GetScrollableAreaIfScrollable(); | 1309 ScrollableArea* area = GetScrollableAreaIfScrollable(); |
1300 if (!area) | 1310 if (!area) |
1301 return IntPoint(); | 1311 return IntPoint(); |
1302 | 1312 |
1303 return IntPoint(area->MinimumScrollOffsetInt().Width(), | 1313 return IntPoint(area->MinimumScrollOffsetInt().Width(), |
1304 area->MinimumScrollOffsetInt().Height()); | 1314 area->MinimumScrollOffsetInt().Height()); |
1305 } | 1315 } |
1306 | 1316 |
1307 IntPoint AXObject::MaximumScrollOffset() const { | 1317 IntPoint AXObjectImpl::MaximumScrollOffset() const { |
1308 ScrollableArea* area = GetScrollableAreaIfScrollable(); | 1318 ScrollableArea* area = GetScrollableAreaIfScrollable(); |
1309 if (!area) | 1319 if (!area) |
1310 return IntPoint(); | 1320 return IntPoint(); |
1311 | 1321 |
1312 return IntPoint(area->MaximumScrollOffsetInt().Width(), | 1322 return IntPoint(area->MaximumScrollOffsetInt().Width(), |
1313 area->MaximumScrollOffsetInt().Height()); | 1323 area->MaximumScrollOffsetInt().Height()); |
1314 } | 1324 } |
1315 | 1325 |
1316 void AXObject::SetScrollOffset(const IntPoint& offset) const { | 1326 void AXObjectImpl::SetScrollOffset(const IntPoint& offset) const { |
1317 ScrollableArea* area = GetScrollableAreaIfScrollable(); | 1327 ScrollableArea* area = GetScrollableAreaIfScrollable(); |
1318 if (!area) | 1328 if (!area) |
1319 return; | 1329 return; |
1320 | 1330 |
1321 // TODO(bokan): This should potentially be a UserScroll. | 1331 // TODO(bokan): This should potentially be a UserScroll. |
1322 area->SetScrollOffset(ScrollOffset(offset.X(), offset.Y()), | 1332 area->SetScrollOffset(ScrollOffset(offset.X(), offset.Y()), |
1323 kProgrammaticScroll); | 1333 kProgrammaticScroll); |
1324 } | 1334 } |
1325 | 1335 |
1326 void AXObject::GetRelativeBounds(AXObject** out_container, | 1336 void AXObjectImpl::GetRelativeBounds( |
1327 FloatRect& out_bounds_in_container, | 1337 AXObjectImpl** out_container, |
1328 SkMatrix44& out_container_transform) const { | 1338 FloatRect& out_bounds_in_container, |
| 1339 SkMatrix44& out_container_transform) const { |
1329 *out_container = nullptr; | 1340 *out_container = nullptr; |
1330 out_bounds_in_container = FloatRect(); | 1341 out_bounds_in_container = FloatRect(); |
1331 out_container_transform.setIdentity(); | 1342 out_container_transform.setIdentity(); |
1332 | 1343 |
1333 // First check if it has explicit bounds, for example if this element is tied | 1344 // First check if it has explicit bounds, for example if this element is tied |
1334 // to a canvas path. When explicit coordinates are provided, the ID of the | 1345 // to a canvas path. When explicit coordinates are provided, the ID of the |
1335 // explicit container element that the coordinates are relative to must be | 1346 // explicit container element that the coordinates are relative to must be |
1336 // provided too. | 1347 // provided too. |
1337 if (!explicit_element_rect_.IsEmpty()) { | 1348 if (!explicit_element_rect_.IsEmpty()) { |
1338 *out_container = AxObjectCache().ObjectFromAXID(explicit_container_id_); | 1349 *out_container = AxObjectCache().ObjectFromAXID(explicit_container_id_); |
1339 if (*out_container) { | 1350 if (*out_container) { |
1340 out_bounds_in_container = FloatRect(explicit_element_rect_); | 1351 out_bounds_in_container = FloatRect(explicit_element_rect_); |
1341 return; | 1352 return; |
1342 } | 1353 } |
1343 } | 1354 } |
1344 | 1355 |
1345 LayoutObject* layout_object = LayoutObjectForRelativeBounds(); | 1356 LayoutObject* layout_object = LayoutObjectForRelativeBounds(); |
1346 if (!layout_object) | 1357 if (!layout_object) |
1347 return; | 1358 return; |
1348 | 1359 |
1349 if (IsWebArea()) { | 1360 if (IsWebArea()) { |
1350 if (layout_object->GetFrame()->View()) | 1361 if (layout_object->GetFrame()->View()) { |
1351 out_bounds_in_container.SetSize( | 1362 out_bounds_in_container.SetSize( |
1352 FloatSize(layout_object->GetFrame()->View()->ContentsSize())); | 1363 FloatSize(layout_object->GetFrame()->View()->ContentsSize())); |
| 1364 } |
1353 return; | 1365 return; |
1354 } | 1366 } |
1355 | 1367 |
1356 // First compute the container. The container must be an ancestor in the | 1368 // First compute the container. The container must be an ancestor in the |
1357 // accessibility tree, and its LayoutObject must be an ancestor in the layout | 1369 // accessibility tree, and its LayoutObject must be an ancestor in the layout |
1358 // tree. Get the first such ancestor that's either scrollable or has a paint | 1370 // tree. Get the first such ancestor that's either scrollable or has a paint |
1359 // layer. | 1371 // layer. |
1360 AXObject* container = ParentObjectUnignored(); | 1372 AXObjectImpl* container = ParentObjectUnignored(); |
1361 LayoutObject* container_layout_object = nullptr; | 1373 LayoutObject* container_layout_object = nullptr; |
1362 while (container) { | 1374 while (container) { |
1363 container_layout_object = container->GetLayoutObject(); | 1375 container_layout_object = container->GetLayoutObject(); |
1364 if (container_layout_object && | 1376 if (container_layout_object && |
1365 container_layout_object->IsBoxModelObject() && | 1377 container_layout_object->IsBoxModelObject() && |
1366 layout_object->IsDescendantOf(container_layout_object)) { | 1378 layout_object->IsDescendantOf(container_layout_object)) { |
1367 if (container->IsScrollableContainer() || | 1379 if (container->IsScrollableContainer() || |
1368 container_layout_object->HasLayer()) | 1380 container_layout_object->HasLayer()) |
1369 break; | 1381 break; |
1370 } | 1382 } |
(...skipping 21 matching lines...) Expand all Loading... |
1392 // scaling, etc. then return the full matrix instead. | 1404 // scaling, etc. then return the full matrix instead. |
1393 TransformationMatrix transform = layout_object->LocalToAncestorTransform( | 1405 TransformationMatrix transform = layout_object->LocalToAncestorTransform( |
1394 ToLayoutBoxModelObject(container_layout_object)); | 1406 ToLayoutBoxModelObject(container_layout_object)); |
1395 if (transform.IsIdentityOr2DTranslation()) { | 1407 if (transform.IsIdentityOr2DTranslation()) { |
1396 out_bounds_in_container.Move(transform.To2DTranslation()); | 1408 out_bounds_in_container.Move(transform.To2DTranslation()); |
1397 } else { | 1409 } else { |
1398 out_container_transform = TransformationMatrix::ToSkMatrix44(transform); | 1410 out_container_transform = TransformationMatrix::ToSkMatrix44(transform); |
1399 } | 1411 } |
1400 } | 1412 } |
1401 | 1413 |
1402 LayoutRect AXObject::GetBoundsInFrameCoordinates() const { | 1414 LayoutRect AXObjectImpl::GetBoundsInFrameCoordinates() const { |
1403 AXObject* container = nullptr; | 1415 AXObjectImpl* container = nullptr; |
1404 FloatRect bounds; | 1416 FloatRect bounds; |
1405 SkMatrix44 transform; | 1417 SkMatrix44 transform; |
1406 GetRelativeBounds(&container, bounds, transform); | 1418 GetRelativeBounds(&container, bounds, transform); |
1407 FloatRect computed_bounds(0, 0, bounds.Width(), bounds.Height()); | 1419 FloatRect computed_bounds(0, 0, bounds.Width(), bounds.Height()); |
1408 while (container && container != this) { | 1420 while (container && container != this) { |
1409 computed_bounds.Move(bounds.X(), bounds.Y()); | 1421 computed_bounds.Move(bounds.X(), bounds.Y()); |
1410 if (!container->IsWebArea()) { | 1422 if (!container->IsWebArea()) { |
1411 computed_bounds.Move(-container->GetScrollOffset().X(), | 1423 computed_bounds.Move(-container->GetScrollOffset().X(), |
1412 -container->GetScrollOffset().Y()); | 1424 -container->GetScrollOffset().Y()); |
1413 } | 1425 } |
1414 if (!transform.isIdentity()) { | 1426 if (!transform.isIdentity()) { |
1415 TransformationMatrix transformation_matrix(transform); | 1427 TransformationMatrix transformation_matrix(transform); |
1416 transformation_matrix.MapRect(computed_bounds); | 1428 transformation_matrix.MapRect(computed_bounds); |
1417 } | 1429 } |
1418 container->GetRelativeBounds(&container, bounds, transform); | 1430 container->GetRelativeBounds(&container, bounds, transform); |
1419 } | 1431 } |
1420 return LayoutRect(computed_bounds); | 1432 return LayoutRect(computed_bounds); |
1421 } | 1433 } |
1422 | 1434 |
1423 // | 1435 // |
1424 // Modify or take an action on an object. | 1436 // Modify or take an action on an object. |
1425 // | 1437 // |
1426 | 1438 |
1427 bool AXObject::Press() { | 1439 bool AXObjectImpl::Press() { |
1428 Document* document = GetDocument(); | 1440 Document* document = GetDocument(); |
1429 if (!document) | 1441 if (!document) |
1430 return false; | 1442 return false; |
1431 | 1443 |
1432 UserGestureIndicator gesture_indicator(DocumentUserGestureToken::Create( | 1444 UserGestureIndicator gesture_indicator(DocumentUserGestureToken::Create( |
1433 document, UserGestureToken::kNewGesture)); | 1445 document, UserGestureToken::kNewGesture)); |
1434 Element* action_elem = ActionElement(); | 1446 Element* action_elem = ActionElement(); |
1435 if (action_elem) { | 1447 if (action_elem) { |
1436 action_elem->AccessKeyAction(true); | 1448 action_elem->AccessKeyAction(true); |
1437 return true; | 1449 return true; |
1438 } | 1450 } |
1439 | 1451 |
1440 if (CanSetFocusAttribute()) { | 1452 if (CanSetFocusAttribute()) { |
1441 SetFocused(true); | 1453 SetFocused(true); |
1442 return true; | 1454 return true; |
1443 } | 1455 } |
1444 | 1456 |
1445 return false; | 1457 return false; |
1446 } | 1458 } |
1447 | 1459 |
1448 void AXObject::ScrollToMakeVisible() const { | 1460 void AXObjectImpl::ScrollToMakeVisible() const { |
1449 IntRect object_rect = PixelSnappedIntRect(GetBoundsInFrameCoordinates()); | 1461 IntRect object_rect = PixelSnappedIntRect(GetBoundsInFrameCoordinates()); |
1450 object_rect.SetLocation(IntPoint()); | 1462 object_rect.SetLocation(IntPoint()); |
1451 ScrollToMakeVisibleWithSubFocus(object_rect); | 1463 ScrollToMakeVisibleWithSubFocus(object_rect); |
1452 } | 1464 } |
1453 | 1465 |
1454 // This is a 1-dimensional scroll offset helper function that's applied | 1466 // This is a 1-dimensional scroll offset helper function that's applied |
1455 // separately in the horizontal and vertical directions, because the | 1467 // separately in the horizontal and vertical directions, because the |
1456 // logic is the same. The goal is to compute the best scroll offset | 1468 // logic is the same. The goal is to compute the best scroll offset |
1457 // in order to make an object visible within a viewport. | 1469 // in order to make an object visible within a viewport. |
1458 // | 1470 // |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1541 | 1553 |
1542 // Exit now if the focus is already within the viewport. | 1554 // Exit now if the focus is already within the viewport. |
1543 if (object_min - current_scroll_offset >= viewport_min && | 1555 if (object_min - current_scroll_offset >= viewport_min && |
1544 object_max - current_scroll_offset <= viewport_max) | 1556 object_max - current_scroll_offset <= viewport_max) |
1545 return current_scroll_offset; | 1557 return current_scroll_offset; |
1546 | 1558 |
1547 // Center the object in the viewport. | 1559 // Center the object in the viewport. |
1548 return (object_min + object_max - viewport_min - viewport_max) / 2; | 1560 return (object_min + object_max - viewport_min - viewport_max) / 2; |
1549 } | 1561 } |
1550 | 1562 |
1551 void AXObject::ScrollToMakeVisibleWithSubFocus(const IntRect& subfocus) const { | 1563 void AXObjectImpl::ScrollToMakeVisibleWithSubFocus( |
| 1564 const IntRect& subfocus) const { |
1552 // Search up the parent chain until we find the first one that's scrollable. | 1565 // Search up the parent chain until we find the first one that's scrollable. |
1553 const AXObject* scroll_parent = ParentObject() ? ParentObject() : this; | 1566 const AXObjectImpl* scroll_parent = ParentObject() ? ParentObject() : this; |
1554 ScrollableArea* scrollable_area = 0; | 1567 ScrollableArea* scrollable_area = 0; |
1555 while (scroll_parent) { | 1568 while (scroll_parent) { |
1556 scrollable_area = scroll_parent->GetScrollableAreaIfScrollable(); | 1569 scrollable_area = scroll_parent->GetScrollableAreaIfScrollable(); |
1557 if (scrollable_area) | 1570 if (scrollable_area) |
1558 break; | 1571 break; |
1559 scroll_parent = scroll_parent->ParentObject(); | 1572 scroll_parent = scroll_parent->ParentObject(); |
1560 } | 1573 } |
1561 if (!scroll_parent || !scrollable_area) | 1574 if (!scroll_parent || !scrollable_area) |
1562 return; | 1575 return; |
1563 | 1576 |
(...skipping 27 matching lines...) Expand all Loading... |
1591 PixelSnappedIntRect(scroll_parent->GetBoundsInFrameCoordinates()); | 1604 PixelSnappedIntRect(scroll_parent->GetBoundsInFrameCoordinates()); |
1592 new_subfocus.Move(new_element_rect.X(), new_element_rect.Y()); | 1605 new_subfocus.Move(new_element_rect.X(), new_element_rect.Y()); |
1593 new_subfocus.Move(-scroll_parent_rect.X(), -scroll_parent_rect.Y()); | 1606 new_subfocus.Move(-scroll_parent_rect.X(), -scroll_parent_rect.Y()); |
1594 | 1607 |
1595 if (scroll_parent->ParentObject()) { | 1608 if (scroll_parent->ParentObject()) { |
1596 // Recursively make sure the scroll parent itself is visible. | 1609 // Recursively make sure the scroll parent itself is visible. |
1597 scroll_parent->ScrollToMakeVisibleWithSubFocus(new_subfocus); | 1610 scroll_parent->ScrollToMakeVisibleWithSubFocus(new_subfocus); |
1598 } else { | 1611 } else { |
1599 // To minimize the number of notifications, only fire one on the topmost | 1612 // To minimize the number of notifications, only fire one on the topmost |
1600 // object that has been scrolled. | 1613 // object that has been scrolled. |
1601 AxObjectCache().PostNotification(const_cast<AXObject*>(this), | 1614 AxObjectCache().PostNotification(const_cast<AXObjectImpl*>(this), |
1602 AXObjectCacheImpl::kAXLocationChanged); | 1615 AXObjectCacheImpl::kAXLocationChanged); |
1603 } | 1616 } |
1604 } | 1617 } |
1605 | 1618 |
1606 void AXObject::ScrollToGlobalPoint(const IntPoint& global_point) const { | 1619 void AXObjectImpl::ScrollToGlobalPoint(const IntPoint& global_point) const { |
1607 // Search up the parent chain and create a vector of all scrollable parent | 1620 // Search up the parent chain and create a vector of all scrollable parent |
1608 // objects and ending with this object itself. | 1621 // objects and ending with this object itself. |
1609 HeapVector<Member<const AXObject>> objects; | 1622 HeapVector<Member<const AXObjectImpl>> objects; |
1610 AXObject* parent_object; | 1623 AXObjectImpl* parent_object; |
1611 for (parent_object = this->ParentObject(); parent_object; | 1624 for (parent_object = this->ParentObject(); parent_object; |
1612 parent_object = parent_object->ParentObject()) { | 1625 parent_object = parent_object->ParentObject()) { |
1613 if (parent_object->GetScrollableAreaIfScrollable()) | 1626 if (parent_object->GetScrollableAreaIfScrollable()) |
1614 objects.push_front(parent_object); | 1627 objects.push_front(parent_object); |
1615 } | 1628 } |
1616 objects.push_back(this); | 1629 objects.push_back(this); |
1617 | 1630 |
1618 // Start with the outermost scrollable (the main window) and try to scroll the | 1631 // Start with the outermost scrollable (the main window) and try to scroll the |
1619 // next innermost object to the given point. | 1632 // next innermost object to the given point. |
1620 int offset_x = 0, offset_y = 0; | 1633 int offset_x = 0, offset_y = 0; |
1621 IntPoint point = global_point; | 1634 IntPoint point = global_point; |
1622 size_t levels = objects.size() - 1; | 1635 size_t levels = objects.size() - 1; |
1623 for (size_t i = 0; i < levels; i++) { | 1636 for (size_t i = 0; i < levels; i++) { |
1624 const AXObject* outer = objects[i]; | 1637 const AXObjectImpl* outer = objects[i]; |
1625 const AXObject* inner = objects[i + 1]; | 1638 const AXObjectImpl* inner = objects[i + 1]; |
1626 ScrollableArea* scrollable_area = outer->GetScrollableAreaIfScrollable(); | 1639 ScrollableArea* scrollable_area = outer->GetScrollableAreaIfScrollable(); |
1627 | 1640 |
1628 IntRect inner_rect = | 1641 IntRect inner_rect = |
1629 inner->IsWebArea() | 1642 inner->IsWebArea() |
1630 ? PixelSnappedIntRect( | 1643 ? PixelSnappedIntRect( |
1631 inner->ParentObject()->GetBoundsInFrameCoordinates()) | 1644 inner->ParentObject()->GetBoundsInFrameCoordinates()) |
1632 : PixelSnappedIntRect(inner->GetBoundsInFrameCoordinates()); | 1645 : PixelSnappedIntRect(inner->GetBoundsInFrameCoordinates()); |
1633 IntRect object_rect = inner_rect; | 1646 IntRect object_rect = inner_rect; |
1634 IntSize scroll_offset = scrollable_area->ScrollOffsetInt(); | 1647 IntSize scroll_offset = scrollable_area->ScrollOffsetInt(); |
1635 | 1648 |
(...skipping 28 matching lines...) Expand all Loading... |
1664 } | 1677 } |
1665 | 1678 |
1666 // To minimize the number of notifications, only fire one on the topmost | 1679 // To minimize the number of notifications, only fire one on the topmost |
1667 // object that has been scrolled. | 1680 // object that has been scrolled. |
1668 DCHECK(objects[0]); | 1681 DCHECK(objects[0]); |
1669 // TODO(nektar): Switch to postNotification(objects[0] and remove |getNode|. | 1682 // TODO(nektar): Switch to postNotification(objects[0] and remove |getNode|. |
1670 AxObjectCache().PostNotification(objects[0]->GetNode(), | 1683 AxObjectCache().PostNotification(objects[0]->GetNode(), |
1671 AXObjectCacheImpl::kAXLocationChanged); | 1684 AXObjectCacheImpl::kAXLocationChanged); |
1672 } | 1685 } |
1673 | 1686 |
1674 void AXObject::SetSequentialFocusNavigationStartingPoint() { | 1687 void AXObjectImpl::SetSequentialFocusNavigationStartingPoint() { |
1675 // Call it on the nearest ancestor that overrides this with a specific | 1688 // Call it on the nearest ancestor that overrides this with a specific |
1676 // implementation. | 1689 // implementation. |
1677 if (ParentObject()) | 1690 if (ParentObject()) |
1678 ParentObject()->SetSequentialFocusNavigationStartingPoint(); | 1691 ParentObject()->SetSequentialFocusNavigationStartingPoint(); |
1679 } | 1692 } |
1680 | 1693 |
1681 void AXObject::NotifyIfIgnoredValueChanged() { | 1694 void AXObjectImpl::NotifyIfIgnoredValueChanged() { |
1682 bool is_ignored = AccessibilityIsIgnored(); | 1695 bool is_ignored = AccessibilityIsIgnored(); |
1683 if (LastKnownIsIgnoredValue() != is_ignored) { | 1696 if (LastKnownIsIgnoredValue() != is_ignored) { |
1684 AxObjectCache().ChildrenChanged(ParentObject()); | 1697 AxObjectCache().ChildrenChanged(ParentObject()); |
1685 SetLastKnownIsIgnoredValue(is_ignored); | 1698 SetLastKnownIsIgnoredValue(is_ignored); |
1686 } | 1699 } |
1687 } | 1700 } |
1688 | 1701 |
1689 void AXObject::SelectionChanged() { | 1702 void AXObjectImpl::SelectionChanged() { |
1690 if (AXObject* parent = ParentObjectIfExists()) | 1703 if (AXObjectImpl* parent = ParentObjectIfExists()) |
1691 parent->SelectionChanged(); | 1704 parent->SelectionChanged(); |
1692 } | 1705 } |
1693 | 1706 |
1694 int AXObject::LineForPosition(const VisiblePosition& position) const { | 1707 int AXObjectImpl::LineForPosition(const VisiblePosition& position) const { |
1695 if (position.IsNull() || !GetNode()) | 1708 if (position.IsNull() || !GetNode()) |
1696 return -1; | 1709 return -1; |
1697 | 1710 |
1698 // If the position is not in the same editable region as this AX object, | 1711 // If the position is not in the same editable region as this AX object, |
1699 // return -1. | 1712 // return -1. |
1700 Node* container_node = position.DeepEquivalent().ComputeContainerNode(); | 1713 Node* container_node = position.DeepEquivalent().ComputeContainerNode(); |
1701 if (!container_node->IsShadowIncludingInclusiveAncestorOf(GetNode()) && | 1714 if (!container_node->IsShadowIncludingInclusiveAncestorOf(GetNode()) && |
1702 !GetNode()->IsShadowIncludingInclusiveAncestorOf(container_node)) | 1715 !GetNode()->IsShadowIncludingInclusiveAncestorOf(container_node)) |
1703 return -1; | 1716 return -1; |
1704 | 1717 |
1705 int line_count = -1; | 1718 int line_count = -1; |
1706 VisiblePosition current_position = position; | 1719 VisiblePosition current_position = position; |
1707 VisiblePosition previous_position; | 1720 VisiblePosition previous_position; |
1708 | 1721 |
1709 // Move up until we get to the top. | 1722 // Move up until we get to the top. |
1710 // FIXME: This only takes us to the top of the rootEditableElement, not the | 1723 // FIXME: This only takes us to the top of the rootEditableElement, not the |
1711 // top of the top document. | 1724 // top of the top document. |
1712 do { | 1725 do { |
1713 previous_position = current_position; | 1726 previous_position = current_position; |
1714 current_position = PreviousLinePosition(current_position, LayoutUnit(), | 1727 current_position = PreviousLinePosition(current_position, LayoutUnit(), |
1715 kHasEditableAXRole); | 1728 kHasEditableAXRole); |
1716 ++line_count; | 1729 ++line_count; |
1717 } while (current_position.IsNotNull() && | 1730 } while (current_position.IsNotNull() && |
1718 !InSameLine(current_position, previous_position)); | 1731 !InSameLine(current_position, previous_position)); |
1719 | 1732 |
1720 return line_count; | 1733 return line_count; |
1721 } | 1734 } |
1722 | 1735 |
1723 bool AXObject::IsARIAControl(AccessibilityRole aria_role) { | 1736 bool AXObjectImpl::IsARIAControl(AccessibilityRole aria_role) { |
1724 return IsARIAInput(aria_role) || aria_role == kButtonRole || | 1737 return IsARIAInput(aria_role) || aria_role == kButtonRole || |
1725 aria_role == kComboBoxRole || aria_role == kSliderRole; | 1738 aria_role == kComboBoxRole || aria_role == kSliderRole; |
1726 } | 1739 } |
1727 | 1740 |
1728 bool AXObject::IsARIAInput(AccessibilityRole aria_role) { | 1741 bool AXObjectImpl::IsARIAInput(AccessibilityRole aria_role) { |
1729 return aria_role == kRadioButtonRole || aria_role == kCheckBoxRole || | 1742 return aria_role == kRadioButtonRole || aria_role == kCheckBoxRole || |
1730 aria_role == kTextFieldRole || aria_role == kSwitchRole || | 1743 aria_role == kTextFieldRole || aria_role == kSwitchRole || |
1731 aria_role == kSearchBoxRole; | 1744 aria_role == kSearchBoxRole; |
1732 } | 1745 } |
1733 | 1746 |
1734 AccessibilityRole AXObject::AriaRoleToWebCoreRole(const String& value) { | 1747 AccessibilityRole AXObjectImpl::AriaRoleToWebCoreRole(const String& value) { |
1735 DCHECK(!value.IsEmpty()); | 1748 DCHECK(!value.IsEmpty()); |
1736 | 1749 |
1737 static const ARIARoleMap* role_map = CreateARIARoleMap(); | 1750 static const ARIARoleMap* role_map = CreateARIARoleMap(); |
1738 | 1751 |
1739 Vector<String> role_vector; | 1752 Vector<String> role_vector; |
1740 value.Split(' ', role_vector); | 1753 value.Split(' ', role_vector); |
1741 AccessibilityRole role = kUnknownRole; | 1754 AccessibilityRole role = kUnknownRole; |
1742 for (const auto& child : role_vector) { | 1755 for (const auto& child : role_vector) { |
1743 role = role_map->at(child); | 1756 role = role_map->at(child); |
1744 if (role) | 1757 if (role) |
1745 return role; | 1758 return role; |
1746 } | 1759 } |
1747 | 1760 |
1748 return role; | 1761 return role; |
1749 } | 1762 } |
1750 | 1763 |
1751 bool AXObject::IsInsideFocusableElementOrARIAWidget(const Node& node) { | 1764 bool AXObjectImpl::IsInsideFocusableElementOrARIAWidget(const Node& node) { |
1752 const Node* cur_node = &node; | 1765 const Node* cur_node = &node; |
1753 do { | 1766 do { |
1754 if (cur_node->IsElementNode()) { | 1767 if (cur_node->IsElementNode()) { |
1755 const Element* element = ToElement(cur_node); | 1768 const Element* element = ToElement(cur_node); |
1756 if (element->IsFocusable()) | 1769 if (element->IsFocusable()) |
1757 return true; | 1770 return true; |
1758 String role = element->getAttribute("role"); | 1771 String role = element->getAttribute("role"); |
1759 if (!role.IsEmpty() && AXObject::IncludesARIAWidgetRole(role)) | 1772 if (!role.IsEmpty() && AXObjectImpl::IncludesARIAWidgetRole(role)) |
1760 return true; | 1773 return true; |
1761 if (HasInteractiveARIAAttribute(*element)) | 1774 if (HasInteractiveARIAAttribute(*element)) |
1762 return true; | 1775 return true; |
1763 } | 1776 } |
1764 cur_node = cur_node->parentNode(); | 1777 cur_node = cur_node->parentNode(); |
1765 } while (cur_node && !isHTMLBodyElement(node)); | 1778 } while (cur_node && !isHTMLBodyElement(node)); |
1766 return false; | 1779 return false; |
1767 } | 1780 } |
1768 | 1781 |
1769 bool AXObject::HasInteractiveARIAAttribute(const Element& element) { | 1782 bool AXObjectImpl::HasInteractiveARIAAttribute(const Element& element) { |
1770 for (size_t i = 0; i < WTF_ARRAY_LENGTH(g_aria_interactive_widget_attributes); | 1783 for (size_t i = 0; i < WTF_ARRAY_LENGTH(g_aria_interactive_widget_attributes); |
1771 ++i) { | 1784 ++i) { |
1772 const char* attribute = g_aria_interactive_widget_attributes[i]; | 1785 const char* attribute = g_aria_interactive_widget_attributes[i]; |
1773 if (element.hasAttribute(attribute)) { | 1786 if (element.hasAttribute(attribute)) { |
1774 return true; | 1787 return true; |
1775 } | 1788 } |
1776 } | 1789 } |
1777 return false; | 1790 return false; |
1778 } | 1791 } |
1779 | 1792 |
1780 bool AXObject::IncludesARIAWidgetRole(const String& role) { | 1793 bool AXObjectImpl::IncludesARIAWidgetRole(const String& role) { |
1781 static const HashSet<String, CaseFoldingHash>* role_set = | 1794 static const HashSet<String, CaseFoldingHash>* role_set = |
1782 CreateARIARoleWidgetSet(); | 1795 CreateARIARoleWidgetSet(); |
1783 | 1796 |
1784 Vector<String> role_vector; | 1797 Vector<String> role_vector; |
1785 role.Split(' ', role_vector); | 1798 role.Split(' ', role_vector); |
1786 for (const auto& child : role_vector) { | 1799 for (const auto& child : role_vector) { |
1787 if (role_set->Contains(child)) | 1800 if (role_set->Contains(child)) |
1788 return true; | 1801 return true; |
1789 } | 1802 } |
1790 return false; | 1803 return false; |
1791 } | 1804 } |
1792 | 1805 |
1793 bool AXObject::NameFromContents() const { | 1806 bool AXObjectImpl::NameFromContents() const { |
1794 // ARIA 1.1, section 5.2.7.5. | 1807 // ARIA 1.1, section 5.2.7.5. |
1795 switch (RoleValue()) { | 1808 switch (RoleValue()) { |
1796 case kAnchorRole: | 1809 case kAnchorRole: |
1797 case kButtonRole: | 1810 case kButtonRole: |
1798 case kCellRole: | 1811 case kCellRole: |
1799 case kCheckBoxRole: | 1812 case kCheckBoxRole: |
1800 case kColumnHeaderRole: | 1813 case kColumnHeaderRole: |
1801 case kDirectoryRole: | 1814 case kDirectoryRole: |
1802 case kDisclosureTriangleRole: | 1815 case kDisclosureTriangleRole: |
1803 case kHeadingRole: | 1816 case kHeadingRole: |
(...skipping 24 matching lines...) Expand all Loading... |
1828 return true; | 1841 return true; |
1829 } | 1842 } |
1830 const Node* node = this->GetNode(); | 1843 const Node* node = this->GetNode(); |
1831 return node && node->IsElementNode() && ToElement(node)->IsFocusable(); | 1844 return node && node->IsElementNode() && ToElement(node)->IsFocusable(); |
1832 } | 1845 } |
1833 default: | 1846 default: |
1834 return false; | 1847 return false; |
1835 } | 1848 } |
1836 } | 1849 } |
1837 | 1850 |
1838 AccessibilityRole AXObject::ButtonRoleType() const { | 1851 AccessibilityRole AXObjectImpl::ButtonRoleType() const { |
1839 // If aria-pressed is present, then it should be exposed as a toggle button. | 1852 // If aria-pressed is present, then it should be exposed as a toggle button. |
1840 // http://www.w3.org/TR/wai-aria/states_and_properties#aria-pressed | 1853 // http://www.w3.org/TR/wai-aria/states_and_properties#aria-pressed |
1841 if (AriaPressedIsPresent()) | 1854 if (AriaPressedIsPresent()) |
1842 return kToggleButtonRole; | 1855 return kToggleButtonRole; |
1843 if (AriaHasPopup()) | 1856 if (AriaHasPopup()) |
1844 return kPopUpButtonRole; | 1857 return kPopUpButtonRole; |
1845 // We don't contemplate RadioButtonRole, as it depends on the input | 1858 // We don't contemplate RadioButtonRole, as it depends on the input |
1846 // type. | 1859 // type. |
1847 | 1860 |
1848 return kButtonRole; | 1861 return kButtonRole; |
1849 } | 1862 } |
1850 | 1863 |
1851 const AtomicString& AXObject::RoleName(AccessibilityRole role) { | 1864 const AtomicString& AXObjectImpl::RoleName(AccessibilityRole role) { |
1852 static const Vector<AtomicString>* role_name_vector = CreateRoleNameVector(); | 1865 static const Vector<AtomicString>* role_name_vector = CreateRoleNameVector(); |
1853 | 1866 |
1854 return role_name_vector->at(role); | 1867 return role_name_vector->at(role); |
1855 } | 1868 } |
1856 | 1869 |
1857 const AtomicString& AXObject::InternalRoleName(AccessibilityRole role) { | 1870 const AtomicString& AXObjectImpl::InternalRoleName(AccessibilityRole role) { |
1858 static const Vector<AtomicString>* internal_role_name_vector = | 1871 static const Vector<AtomicString>* internal_role_name_vector = |
1859 CreateInternalRoleNameVector(); | 1872 CreateInternalRoleNameVector(); |
1860 | 1873 |
1861 return internal_role_name_vector->at(role); | 1874 return internal_role_name_vector->at(role); |
1862 } | 1875 } |
1863 | 1876 |
1864 DEFINE_TRACE(AXObject) { | 1877 DEFINE_TRACE(AXObjectImpl) { |
1865 visitor->Trace(children_); | 1878 visitor->Trace(children_); |
1866 visitor->Trace(parent_); | 1879 visitor->Trace(parent_); |
1867 visitor->Trace(cached_live_region_root_); | 1880 visitor->Trace(cached_live_region_root_); |
1868 visitor->Trace(ax_object_cache_); | 1881 visitor->Trace(ax_object_cache_); |
1869 } | 1882 } |
1870 | 1883 |
1871 } // namespace blink | 1884 } // namespace blink |
OLD | NEW |