/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 | } |