Bug 1769547 - Do not MOZ_CRASH() on missing process r=nika
[gecko.git] / accessible / mac / DocAccessibleWrap.mm
blob8e851e7920f979aef7593dceb98aaf0f90e28d0c
1 /* clang-format off */
2 /* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3 /* clang-format on */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "DocAccessibleWrap.h"
9 #include "DocAccessible-inl.h"
11 #import "mozAccessible.h"
12 #import "MOXTextMarkerDelegate.h"
14 using namespace mozilla;
15 using namespace mozilla::a11y;
17 DocAccessibleWrap::DocAccessibleWrap(dom::Document* aDocument,
18                                      PresShell* aPresShell)
19     : DocAccessible(aDocument, aPresShell) {}
21 void DocAccessibleWrap::Shutdown() {
22   [MOXTextMarkerDelegate destroyForDoc:this];
23   DocAccessible::Shutdown();
26 DocAccessibleWrap::~DocAccessibleWrap() {}
28 void DocAccessibleWrap::AttributeChanged(dom::Element* aElement,
29                                          int32_t aNameSpaceID,
30                                          nsAtom* aAttribute, int32_t aModType,
31                                          const nsAttrValue* aOldValue) {
32   DocAccessible::AttributeChanged(aElement, aNameSpaceID, aAttribute, aModType,
33                                   aOldValue);
34   if (aAttribute == nsGkAtoms::aria_live) {
35     LocalAccessible* accessible =
36         mContent != aElement ? GetAccessible(aElement) : this;
37     if (!accessible) {
38       return;
39     }
41     static const dom::Element::AttrValuesArray sLiveRegionValues[] = {
42         nsGkAtoms::OFF, nsGkAtoms::polite, nsGkAtoms::assertive, nullptr};
43     int32_t attrValue =
44         aElement->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::aria_live,
45                                   sLiveRegionValues, eIgnoreCase);
46     if (attrValue > 0) {
47       if (!aOldValue || aOldValue->IsEmptyString() ||
48           aOldValue->Equals(nsGkAtoms::OFF, eIgnoreCase)) {
49         // This element just got an active aria-live attribute value
50         FireDelayedEvent(nsIAccessibleEvent::EVENT_LIVE_REGION_ADDED,
51                          accessible);
52       }
53     } else {
54       if (aOldValue && (aOldValue->Equals(nsGkAtoms::polite, eIgnoreCase) ||
55                         aOldValue->Equals(nsGkAtoms::assertive, eIgnoreCase))) {
56         // This element lost an active live region
57         FireDelayedEvent(nsIAccessibleEvent::EVENT_LIVE_REGION_REMOVED,
58                          accessible);
59       } else if (attrValue == 0) {
60         // aria-live="off", check if its a role-based live region that
61         // needs to be removed.
62         if (const nsRoleMapEntry* roleMap = accessible->ARIARoleMap()) {
63           // aria role defines it as a live region. It's live!
64           if (roleMap->liveAttRule == ePoliteLiveAttr ||
65               roleMap->liveAttRule == eAssertiveLiveAttr) {
66             FireDelayedEvent(nsIAccessibleEvent::EVENT_LIVE_REGION_REMOVED,
67                              accessible);
68           }
69         } else if (nsStaticAtom* value = GetAccService()->MarkupAttribute(
70                        aElement, nsGkAtoms::aria_live)) {
71           // HTML element defines it as a live region. It's live!
72           if (value == nsGkAtoms::polite || value == nsGkAtoms::assertive) {
73             FireDelayedEvent(nsIAccessibleEvent::EVENT_LIVE_REGION_REMOVED,
74                              accessible);
75           }
76         }
77       }
78     }
79   }
82 void DocAccessibleWrap::QueueNewLiveRegion(LocalAccessible* aAccessible) {
83   if (!aAccessible) {
84     return;
85   }
87   mNewLiveRegions.Insert(aAccessible->UniqueID());
90 void DocAccessibleWrap::ProcessNewLiveRegions() {
91   for (const auto& uniqueID : mNewLiveRegions) {
92     if (LocalAccessible* liveRegion =
93             GetAccessibleByUniqueID(const_cast<void*>(uniqueID))) {
94       FireDelayedEvent(nsIAccessibleEvent::EVENT_LIVE_REGION_ADDED, liveRegion);
95     }
96   }
98   mNewLiveRegions.Clear();
101 void DocAccessibleWrap::DoInitialUpdate() {
102   DocAccessible::DoInitialUpdate();
103   ProcessNewLiveRegions();