Bug 1687263: part 4) Defer and in some cases avoid removing spellchecking-ranges...
[gecko.git] / accessible / ipc / RemoteAccessibleBase.cpp
blob57cf9df7803cbaf3abb8f08415fcf2126572f6b5
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/RemoteAccessibleBase.h"
12 #include "mozilla/a11y/RemoteAccessible.h"
13 #include "mozilla/a11y/Role.h"
14 #include "mozilla/dom/Element.h"
15 #include "mozilla/dom/BrowserParent.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 RemoteAccessibleBase<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 (!IsOuterDoc()) {
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 RemoteAccessibleBase<Derived>::SetChildDoc(
52 DocAccessibleParent* aChildDoc) {
53 MOZ_ASSERT(aChildDoc);
54 MOZ_ASSERT(mChildren.Length() == 0);
55 mChildren.AppendElement(aChildDoc);
58 template <class Derived>
59 void RemoteAccessibleBase<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 RemoteAccessibleBase<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 RemoteAccessibleBase<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* RemoteAccessibleBase<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 LocalAccessible* RemoteAccessibleBase<Derived>::OuterDocOfRemoteBrowser()
119 const {
120 auto tab = static_cast<dom::BrowserParent*>(mDoc->Manager());
121 dom::Element* frame = tab->GetOwnerElement();
122 NS_ASSERTION(frame, "why isn't the tab in a frame!");
123 if (!frame) return nullptr;
125 DocAccessible* chromeDoc = GetExistingDocAccessible(frame->OwnerDoc());
127 return chromeDoc ? chromeDoc->GetAccessible(frame) : nullptr;
130 template <class Derived>
131 void RemoteAccessibleBase<Derived>::SetParent(Derived* aParent) {
132 MOZ_ASSERT(IsDoc(), "we should only reparent documents");
133 if (!aParent) {
134 mParent = kNoParent;
135 } else {
136 MOZ_ASSERT(!aParent->IsDoc());
137 mParent = aParent->ID();
141 template <class Derived>
142 Derived* RemoteAccessibleBase<Derived>::RemoteParent() const {
143 if (mParent == kNoParent) {
144 return nullptr;
147 // if we are not a document then are parent is another proxy in the same
148 // document. That means we can just ask our document for the proxy with our
149 // parent id.
150 if (!IsDoc()) {
151 return Document()->GetAccessible(mParent);
154 // If we are a top level document then our parent is not a proxy.
155 if (AsDoc()->IsTopLevel()) {
156 return nullptr;
159 // Finally if we are a non top level document then our parent id is for a
160 // proxy in our parent document so get the proxy from there.
161 DocAccessibleParent* parentDoc = AsDoc()->ParentDoc();
162 MOZ_ASSERT(parentDoc);
163 MOZ_ASSERT(mParent);
164 return parentDoc->GetAccessible(mParent);
167 template class RemoteAccessibleBase<RemoteAccessible>;
169 } // namespace a11y
170 } // namespace mozilla