Bug 1526581 [wpt PR 15249] - CODEOWNERS cleanup, a=testonly
[gecko.git] / accessible / ipc / ProxyAccessibleBase.cpp
blob83b431ca0b2a06c8e1ba9c5d77cdcad4858d227b
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/. */
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"
20 namespace mozilla {
21 namespace a11y {
23 template <class Derived>
24 void ProxyAccessibleBase<Derived>::Shutdown() {
25 MOZ_DIAGNOSTIC_ASSERT(!IsDoc());
26 xpcAccessibleDocument* xpcDoc =
27 GetAccService()->GetCachedXPCDocument(Document());
28 if (xpcDoc) {
29 xpcDoc->NotifyOfShutdown(static_cast<Derived*>(this));
32 // XXX Ideally this wouldn't be necessary, but it seems OuterDoc accessibles
33 // can be destroyed before the doc they own.
34 uint32_t childCount = mChildren.Length();
35 if (!mOuterDoc) {
36 for (uint32_t idx = 0; idx < childCount; idx++) mChildren[idx]->Shutdown();
37 } else {
38 if (childCount > 1) {
39 MOZ_CRASH("outer doc has too many documents!");
40 } else if (childCount == 1) {
41 mChildren[0]->AsDoc()->Unbind();
45 mChildren.Clear();
46 ProxyDestroyed(static_cast<Derived*>(this));
47 mDoc->RemoveAccessible(static_cast<Derived*>(this));
50 template <class Derived>
51 void ProxyAccessibleBase<Derived>::SetChildDoc(DocAccessibleParent* aChildDoc) {
52 MOZ_ASSERT(aChildDoc);
53 MOZ_ASSERT(mChildren.Length() == 0);
54 mChildren.AppendElement(aChildDoc);
55 mOuterDoc = true;
58 template <class Derived>
59 void ProxyAccessibleBase<Derived>::ClearChildDoc(
60 DocAccessibleParent* aChildDoc) {
61 MOZ_ASSERT(aChildDoc);
62 // This is possible if we're replacing one document with another: Doc 1
63 // has not had a chance to remove itself, but was already replaced by Doc 2
64 // in SetChildDoc(). This could result in two subsequent calls to
65 // ClearChildDoc() even though mChildren.Length() == 1.
66 MOZ_ASSERT(mChildren.Length() <= 1);
67 mChildren.RemoveElement(aChildDoc);
70 template <class Derived>
71 uint32_t ProxyAccessibleBase<Derived>::EmbeddedChildCount() const {
72 size_t count = 0, kids = mChildren.Length();
73 for (size_t i = 0; i < kids; i++) {
74 if (mChildren[i]->IsEmbeddedObject()) {
75 count++;
79 return count;
82 template <class Derived>
83 int32_t ProxyAccessibleBase<Derived>::IndexOfEmbeddedChild(
84 const Derived* aChild) {
85 size_t index = 0, kids = mChildren.Length();
86 for (size_t i = 0; i < kids; i++) {
87 if (mChildren[i]->IsEmbeddedObject()) {
88 if (mChildren[i] == aChild) {
89 return index;
92 index++;
96 return -1;
99 template <class Derived>
100 Derived* ProxyAccessibleBase<Derived>::EmbeddedChildAt(size_t aChildIdx) {
101 size_t index = 0, kids = mChildren.Length();
102 for (size_t i = 0; i < kids; i++) {
103 if (!mChildren[i]->IsEmbeddedObject()) {
104 continue;
107 if (index == aChildIdx) {
108 return mChildren[i];
111 index++;
114 return nullptr;
117 template <class Derived>
118 Accessible* ProxyAccessibleBase<Derived>::OuterDocOfRemoteBrowser() const {
119 auto tab = static_cast<dom::TabParent*>(mDoc->Manager());
120 dom::Element* frame = tab->GetOwnerElement();
121 NS_ASSERTION(frame, "why isn't the tab in a frame!");
122 if (!frame) return nullptr;
124 DocAccessible* chromeDoc = GetExistingDocAccessible(frame->OwnerDoc());
126 return chromeDoc ? chromeDoc->GetAccessible(frame) : nullptr;
129 template <class Derived>
130 void ProxyAccessibleBase<Derived>::SetParent(Derived* aParent) {
131 MOZ_ASSERT(IsDoc(), "we should only reparent documents");
132 if (!aParent) {
133 mParent = kNoParent;
134 } else {
135 MOZ_ASSERT(!aParent->IsDoc());
136 mParent = aParent->ID();
140 template <class Derived>
141 Derived* ProxyAccessibleBase<Derived>::Parent() const {
142 if (mParent == kNoParent) {
143 return nullptr;
146 // if we are not a document then are parent is another proxy in the same
147 // document. That means we can just ask our document for the proxy with our
148 // parent id.
149 if (!IsDoc()) {
150 return Document()->GetAccessible(mParent);
153 // If we are a top level document then our parent is not a proxy.
154 if (AsDoc()->IsTopLevel()) {
155 return nullptr;
158 // Finally if we are a non top level document then our parent id is for a
159 // proxy in our parent document so get the proxy from there.
160 DocAccessibleParent* parentDoc = AsDoc()->ParentDoc();
161 MOZ_ASSERT(parentDoc);
162 MOZ_ASSERT(mParent);
163 return parentDoc->GetAccessible(mParent);
166 template class ProxyAccessibleBase<ProxyAccessible>;
168 } // namespace a11y
169 } // namespace mozilla