Coverage Report

Created: 2018-09-25 14:53

/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