Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/accessible/generic/OuterDocAccessible.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#include "OuterDocAccessible.h"
7
8
#include "Accessible-inl.h"
9
#include "nsAccUtils.h"
10
#include "DocAccessible-inl.h"
11
#include "mozilla/a11y/DocAccessibleParent.h"
12
#include "mozilla/dom/TabParent.h"
13
#include "Role.h"
14
#include "States.h"
15
16
#ifdef A11Y_LOG
17
#include "Logging.h"
18
#endif
19
20
using namespace mozilla;
21
using namespace mozilla::a11y;
22
23
////////////////////////////////////////////////////////////////////////////////
24
// OuterDocAccessible
25
////////////////////////////////////////////////////////////////////////////////
26
27
OuterDocAccessible::
28
  OuterDocAccessible(nsIContent* aContent, DocAccessible* aDoc) :
29
  AccessibleWrap(aContent, aDoc)
30
0
{
31
0
  mType = eOuterDocType;
32
0
33
#ifdef XP_WIN
34
  if (DocAccessibleParent* remoteDoc = RemoteChildDoc()) {
35
    remoteDoc->SendParentCOMProxy();
36
  }
37
#endif
38
39
0
  // Request document accessible for the content document to make sure it's
40
0
  // created. It will appended to outerdoc accessible children asynchronously.
41
0
  nsIDocument* outerDoc = mContent->GetUncomposedDoc();
42
0
  if (outerDoc) {
43
0
    nsIDocument* innerDoc = outerDoc->GetSubDocumentFor(mContent);
44
0
    if (innerDoc)
45
0
      GetAccService()->GetDocAccessible(innerDoc);
46
0
  }
47
0
}
48
49
OuterDocAccessible::~OuterDocAccessible()
50
0
{
51
0
}
52
53
////////////////////////////////////////////////////////////////////////////////
54
// Accessible public (DON'T add methods here)
55
56
role
57
OuterDocAccessible::NativeRole() const
58
0
{
59
0
  return roles::INTERNAL_FRAME;
60
0
}
61
62
Accessible*
63
OuterDocAccessible::ChildAtPoint(int32_t aX, int32_t aY,
64
                                 EWhichChildAtPoint aWhichChild)
65
0
{
66
0
  nsIntRect docRect = Bounds();
67
0
  if (!docRect.Contains(aX, aY))
68
0
    return nullptr;
69
0
70
0
  // Always return the inner doc as direct child accessible unless bounds
71
0
  // outside of it.
72
0
  Accessible* child = GetChildAt(0);
73
0
  NS_ENSURE_TRUE(child, nullptr);
74
0
75
0
  if (aWhichChild == eDeepestChild)
76
0
    return child->ChildAtPoint(aX, aY, eDeepestChild);
77
0
  return child;
78
0
}
79
80
////////////////////////////////////////////////////////////////////////////////
81
// Accessible public
82
83
void
84
OuterDocAccessible::Shutdown()
85
0
{
86
0
#ifdef A11Y_LOG
87
0
  if (logging::IsEnabled(logging::eDocDestroy))
88
0
    logging::OuterDocDestroy(this);
89
0
#endif
90
0
91
0
  Accessible* child = mChildren.SafeElementAt(0, nullptr);
92
0
  if (child) {
93
0
#ifdef A11Y_LOG
94
0
    if (logging::IsEnabled(logging::eDocDestroy)) {
95
0
      logging::DocDestroy("outerdoc's child document rebind is scheduled",
96
0
                          child->AsDoc()->DocumentNode());
97
0
    }
98
0
#endif
99
0
    RemoveChild(child);
100
0
101
0
    // XXX: sometimes outerdoc accessible is shutdown because of layout style
102
0
    // change however the presshell of underlying document isn't destroyed and
103
0
    // the document doesn't get pagehide events. Schedule a document rebind
104
0
    // to its parent document. Otherwise a document accessible may be lost if
105
0
    // its outerdoc has being recreated (see bug 862863 for details).
106
0
    if (!mDoc->IsDefunct()) {
107
0
      MOZ_ASSERT(!child->IsDefunct(), "Attempt to reattach shutdown document accessible");
108
0
      if (!child->IsDefunct()) {
109
0
        mDoc->BindChildDocument(child->AsDoc());
110
0
      }
111
0
    }
112
0
  }
113
0
114
0
  AccessibleWrap::Shutdown();
115
0
}
116
117
bool
118
OuterDocAccessible::InsertChildAt(uint32_t aIdx, Accessible* aAccessible)
119
0
{
120
0
  MOZ_RELEASE_ASSERT(aAccessible->IsDoc(),
121
0
                     "OuterDocAccessible can have a document child only!");
122
0
123
0
  // We keep showing the old document for a bit after creating the new one,
124
0
  // and while building the new DOM and frame tree. That's done on purpose
125
0
  // to avoid weird flashes of default background color.
126
0
  // The old viewer will be destroyed after the new one is created.
127
0
  // For a11y, it should be safe to shut down the old document now.
128
0
  if (mChildren.Length())
129
0
    mChildren[0]->Shutdown();
130
0
131
0
  if (!AccessibleWrap::InsertChildAt(0, aAccessible))
132
0
    return false;
133
0
134
0
#ifdef A11Y_LOG
135
0
  if (logging::IsEnabled(logging::eDocCreate)) {
136
0
    logging::DocCreate("append document to outerdoc",
137
0
                       aAccessible->AsDoc()->DocumentNode());
138
0
    logging::Address("outerdoc", this);
139
0
  }
140
0
#endif
141
0
142
0
  return true;
143
0
}
144
145
bool
146
OuterDocAccessible::RemoveChild(Accessible* aAccessible)
147
0
{
148
0
  Accessible* child = mChildren.SafeElementAt(0, nullptr);
149
0
  MOZ_ASSERT(child == aAccessible, "Wrong child to remove!");
150
0
  if (child != aAccessible) {
151
0
    return false;
152
0
  }
153
0
154
0
#ifdef A11Y_LOG
155
0
  if (logging::IsEnabled(logging::eDocDestroy)) {
156
0
    logging::DocDestroy("remove document from outerdoc",
157
0
                        child->AsDoc()->DocumentNode(), child->AsDoc());
158
0
    logging::Address("outerdoc", this);
159
0
  }
160
0
#endif
161
0
162
0
  bool wasRemoved = AccessibleWrap::RemoveChild(child);
163
0
164
0
  NS_ASSERTION(!mChildren.Length(),
165
0
               "This child document of outerdoc accessible wasn't removed!");
166
0
167
0
  return wasRemoved;
168
0
}
169
170
bool
171
OuterDocAccessible::IsAcceptableChild(nsIContent* aEl) const
172
0
{
173
0
  // outer document accessible doesn't not participate in ordinal tree
174
0
  // mutations.
175
0
  return false;
176
0
}
177
178
#if defined(XP_WIN)
179
180
// On Windows e10s, since we don't cache in the chrome process, these next two
181
// functions must be implemented so that we properly cross the chrome-to-content
182
// boundary when traversing.
183
184
uint32_t
185
OuterDocAccessible::ChildCount() const
186
{
187
  uint32_t result = mChildren.Length();
188
  if (!result && RemoteChildDoc()) {
189
    result = 1;
190
  }
191
  return result;
192
}
193
194
Accessible*
195
OuterDocAccessible::GetChildAt(uint32_t aIndex) const
196
{
197
  Accessible* result = AccessibleWrap::GetChildAt(aIndex);
198
  if (result || aIndex) {
199
    return result;
200
  }
201
  // If we are asking for child 0 and GetChildAt doesn't return anything, try
202
  // to get the remote child doc and return that instead.
203
  ProxyAccessible* remoteChild = RemoteChildDoc();
204
  if (!remoteChild) {
205
    return nullptr;
206
  }
207
  return WrapperFor(remoteChild);
208
}
209
210
#endif // defined(XP_WIN)
211
212
DocAccessibleParent*
213
OuterDocAccessible::RemoteChildDoc() const
214
0
{
215
0
  dom::TabParent* tab = dom::TabParent::GetFrom(GetContent());
216
0
  if (!tab)
217
0
    return nullptr;
218
0
219
0
  return tab->GetTopLevelDocAccessible();
220
0
}