/src/mozilla-central/accessible/ipc/ProxyAccessibleBase.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include "DocAccessible.h" |
8 | | #include "mozilla/a11y/DocAccessibleParent.h" |
9 | | #include "mozilla/a11y/DocManager.h" |
10 | | #include "mozilla/a11y/Platform.h" |
11 | | #include "mozilla/a11y/ProxyAccessibleBase.h" |
12 | | #include "mozilla/a11y/ProxyAccessible.h" |
13 | | #include "mozilla/a11y/Role.h" |
14 | | #include "mozilla/dom/Element.h" |
15 | | #include "mozilla/dom/TabParent.h" |
16 | | #include "mozilla/Unused.h" |
17 | | #include "RelationType.h" |
18 | | #include "xpcAccessibleDocument.h" |
19 | | |
20 | | namespace mozilla { |
21 | | namespace a11y { |
22 | | |
23 | | template <class Derived> |
24 | | void |
25 | | ProxyAccessibleBase<Derived>::Shutdown() |
26 | 0 | { |
27 | 0 | MOZ_DIAGNOSTIC_ASSERT(!IsDoc()); |
28 | 0 | xpcAccessibleDocument* xpcDoc = |
29 | 0 | GetAccService()->GetCachedXPCDocument(Document()); |
30 | 0 | if (xpcDoc) { |
31 | 0 | xpcDoc->NotifyOfShutdown(static_cast<Derived*>(this)); |
32 | 0 | } |
33 | 0 |
|
34 | 0 | // XXX Ideally this wouldn't be necessary, but it seems OuterDoc accessibles |
35 | 0 | // can be destroyed before the doc they own. |
36 | 0 | uint32_t childCount = mChildren.Length(); |
37 | 0 | if (!mOuterDoc) { |
38 | 0 | for (uint32_t idx = 0; idx < childCount; idx++) |
39 | 0 | mChildren[idx]->Shutdown(); |
40 | 0 | } else { |
41 | 0 | if (childCount > 1) { |
42 | 0 | MOZ_CRASH("outer doc has too many documents!"); |
43 | 0 | } else if (childCount == 1) { |
44 | 0 | mChildren[0]->AsDoc()->Unbind(); |
45 | 0 | } |
46 | 0 | } |
47 | 0 |
|
48 | 0 | mChildren.Clear(); |
49 | 0 | ProxyDestroyed(static_cast<Derived*>(this)); |
50 | 0 | mDoc->RemoveAccessible(static_cast<Derived*>(this)); |
51 | 0 | } |
52 | | |
53 | | template <class Derived> |
54 | | void |
55 | | ProxyAccessibleBase<Derived>::SetChildDoc(DocAccessibleParent* aChildDoc) |
56 | 0 | { |
57 | 0 | MOZ_ASSERT(aChildDoc); |
58 | 0 | MOZ_ASSERT(mChildren.Length() == 0); |
59 | 0 | mChildren.AppendElement(aChildDoc); |
60 | 0 | mOuterDoc = true; |
61 | 0 | } |
62 | | |
63 | | template <class Derived> |
64 | | void |
65 | | ProxyAccessibleBase<Derived>::ClearChildDoc(DocAccessibleParent* aChildDoc) |
66 | 0 | { |
67 | 0 | MOZ_ASSERT(aChildDoc); |
68 | 0 | // This is possible if we're replacing one document with another: Doc 1 |
69 | 0 | // has not had a chance to remove itself, but was already replaced by Doc 2 |
70 | 0 | // in SetChildDoc(). This could result in two subsequent calls to |
71 | 0 | // ClearChildDoc() even though mChildren.Length() == 1. |
72 | 0 | MOZ_ASSERT(mChildren.Length() <= 1); |
73 | 0 | mChildren.RemoveElement(aChildDoc); |
74 | 0 | } |
75 | | |
76 | | template <class Derived> |
77 | | bool |
78 | | ProxyAccessibleBase<Derived>::MustPruneChildren() const |
79 | 0 | { |
80 | 0 | // this is the equivalent to nsAccUtils::MustPrune for proxies and should be |
81 | 0 | // kept in sync with that. |
82 | 0 | if (mRole != roles::MENUITEM && mRole != roles::COMBOBOX_OPTION |
83 | 0 | && mRole != roles::OPTION && mRole != roles::ENTRY |
84 | 0 | && mRole != roles::FLAT_EQUATION && mRole != roles::PASSWORD_TEXT |
85 | 0 | && mRole != roles::PUSHBUTTON && mRole != roles::TOGGLE_BUTTON |
86 | 0 | && mRole != roles::GRAPHIC && mRole != roles::SLIDER |
87 | 0 | && mRole != roles::PROGRESSBAR && mRole != roles::SEPARATOR) |
88 | 0 | return false; |
89 | 0 | |
90 | 0 | if (mChildren.Length() != 1) |
91 | 0 | return false; |
92 | 0 | |
93 | 0 | return mChildren[0]->Role() == roles::TEXT_LEAF |
94 | 0 | || mChildren[0]->Role() == roles::STATICTEXT; |
95 | 0 | } |
96 | | |
97 | | template <class Derived> |
98 | | uint32_t |
99 | | ProxyAccessibleBase<Derived>::EmbeddedChildCount() const |
100 | 0 | { |
101 | 0 | size_t count = 0, kids = mChildren.Length(); |
102 | 0 | for (size_t i = 0; i < kids; i++) { |
103 | 0 | if (mChildren[i]->IsEmbeddedObject()) { |
104 | 0 | count++; |
105 | 0 | } |
106 | 0 | } |
107 | 0 |
|
108 | 0 | return count; |
109 | 0 | } |
110 | | |
111 | | template <class Derived> |
112 | | int32_t |
113 | | ProxyAccessibleBase<Derived>::IndexOfEmbeddedChild(const Derived* aChild) |
114 | 0 | { |
115 | 0 | size_t index = 0, kids = mChildren.Length(); |
116 | 0 | for (size_t i = 0; i < kids; i++) { |
117 | 0 | if (mChildren[i]->IsEmbeddedObject()) { |
118 | 0 | if (mChildren[i] == aChild) { |
119 | 0 | return index; |
120 | 0 | } |
121 | 0 | |
122 | 0 | index++; |
123 | 0 | } |
124 | 0 | } |
125 | 0 |
|
126 | 0 | return -1; |
127 | 0 | } |
128 | | |
129 | | template <class Derived> |
130 | | Derived* |
131 | | ProxyAccessibleBase<Derived>::EmbeddedChildAt(size_t aChildIdx) |
132 | 0 | { |
133 | 0 | size_t index = 0, kids = mChildren.Length(); |
134 | 0 | for (size_t i = 0; i < kids; i++) { |
135 | 0 | if (!mChildren[i]->IsEmbeddedObject()) { |
136 | 0 | continue; |
137 | 0 | } |
138 | 0 | |
139 | 0 | if (index == aChildIdx) { |
140 | 0 | return mChildren[i]; |
141 | 0 | } |
142 | 0 | |
143 | 0 | index++; |
144 | 0 | } |
145 | 0 |
|
146 | 0 | return nullptr; |
147 | 0 | } |
148 | | |
149 | | template <class Derived> |
150 | | Accessible* |
151 | | ProxyAccessibleBase<Derived>::OuterDocOfRemoteBrowser() const |
152 | 0 | { |
153 | 0 | auto tab = static_cast<dom::TabParent*>(mDoc->Manager()); |
154 | 0 | dom::Element* frame = tab->GetOwnerElement(); |
155 | 0 | NS_ASSERTION(frame, "why isn't the tab in a frame!"); |
156 | 0 | if (!frame) |
157 | 0 | return nullptr; |
158 | 0 | |
159 | 0 | DocAccessible* chromeDoc = GetExistingDocAccessible(frame->OwnerDoc()); |
160 | 0 |
|
161 | 0 | return chromeDoc ? chromeDoc->GetAccessible(frame) : nullptr; |
162 | 0 | } |
163 | | |
164 | | template<class Derived> |
165 | | void |
166 | | ProxyAccessibleBase<Derived>::SetParent(Derived* aParent) |
167 | 0 | { |
168 | 0 | MOZ_ASSERT(IsDoc(), "we should only reparent documents"); |
169 | 0 | if (!aParent) { |
170 | 0 | mParent = kNoParent; |
171 | 0 | } else { |
172 | 0 | MOZ_ASSERT(!aParent->IsDoc()); |
173 | 0 | mParent = aParent->ID(); |
174 | 0 | } |
175 | 0 | } |
176 | | |
177 | | template<class Derived> |
178 | | Derived* |
179 | | ProxyAccessibleBase<Derived>::Parent() const |
180 | 0 | { |
181 | 0 | if (mParent == kNoParent) { |
182 | 0 | return nullptr; |
183 | 0 | } |
184 | 0 | |
185 | 0 | // if we are not a document then are parent is another proxy in the same |
186 | 0 | // document. That means we can just ask our document for the proxy with our |
187 | 0 | // parent id. |
188 | 0 | if (!IsDoc()) { |
189 | 0 | return Document()->GetAccessible(mParent); |
190 | 0 | } |
191 | 0 | |
192 | 0 | // If we are a top level document then our parent is not a proxy. |
193 | 0 | if (AsDoc()->IsTopLevel()) { |
194 | 0 | return nullptr; |
195 | 0 | } |
196 | 0 | |
197 | 0 | // Finally if we are a non top level document then our parent id is for a |
198 | 0 | // proxy in our parent document so get the proxy from there. |
199 | 0 | DocAccessibleParent* parentDoc = AsDoc()->ParentDoc(); |
200 | 0 | MOZ_ASSERT(parentDoc); |
201 | 0 | MOZ_ASSERT(mParent); |
202 | 0 | return parentDoc->GetAccessible(mParent); |
203 | 0 | } |
204 | | |
205 | | template class ProxyAccessibleBase<ProxyAccessible>; |
206 | | |
207 | | } // namespace a11y |
208 | | } // namespace mozilla |