Line data Source code
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 0 : OuterDocAccessible::
28 0 : OuterDocAccessible(nsIContent* aContent, DocAccessible* aDoc) :
29 0 : AccessibleWrap(aContent, aDoc)
30 : {
31 0 : mType = eOuterDocType;
32 :
33 : #ifdef XP_WIN
34 : if (DocAccessibleParent* remoteDoc = RemoteChildDoc()) {
35 : remoteDoc->SendParentCOMProxy();
36 : }
37 : #endif
38 :
39 : // Request document accessible for the content document to make sure it's
40 : // 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 : }
47 0 : }
48 :
49 0 : OuterDocAccessible::~OuterDocAccessible()
50 : {
51 0 : }
52 :
53 : ////////////////////////////////////////////////////////////////////////////////
54 : // nsISupports
55 :
56 0 : NS_IMPL_ISUPPORTS_INHERITED0(OuterDocAccessible,
57 : Accessible)
58 :
59 : ////////////////////////////////////////////////////////////////////////////////
60 : // Accessible public (DON'T add methods here)
61 :
62 : role
63 0 : OuterDocAccessible::NativeRole()
64 : {
65 0 : return roles::INTERNAL_FRAME;
66 : }
67 :
68 : Accessible*
69 0 : OuterDocAccessible::ChildAtPoint(int32_t aX, int32_t aY,
70 : EWhichChildAtPoint aWhichChild)
71 : {
72 0 : nsIntRect docRect = Bounds();
73 0 : if (aX < docRect.x || aX >= docRect.x + docRect.width ||
74 0 : aY < docRect.y || aY >= docRect.y + docRect.height)
75 0 : return nullptr;
76 :
77 : // Always return the inner doc as direct child accessible unless bounds
78 : // outside of it.
79 0 : Accessible* child = GetChildAt(0);
80 0 : NS_ENSURE_TRUE(child, nullptr);
81 :
82 0 : if (aWhichChild == eDeepestChild)
83 0 : return child->ChildAtPoint(aX, aY, eDeepestChild);
84 0 : return child;
85 : }
86 :
87 : ////////////////////////////////////////////////////////////////////////////////
88 : // Accessible public
89 :
90 : void
91 0 : OuterDocAccessible::Shutdown()
92 : {
93 : #ifdef A11Y_LOG
94 0 : if (logging::IsEnabled(logging::eDocDestroy))
95 0 : logging::OuterDocDestroy(this);
96 : #endif
97 :
98 0 : Accessible* child = mChildren.SafeElementAt(0, nullptr);
99 0 : if (child) {
100 : #ifdef A11Y_LOG
101 0 : if (logging::IsEnabled(logging::eDocDestroy)) {
102 0 : logging::DocDestroy("outerdoc's child document rebind is scheduled",
103 0 : child->AsDoc()->DocumentNode());
104 : }
105 : #endif
106 0 : RemoveChild(child);
107 :
108 : // XXX: sometimes outerdoc accessible is shutdown because of layout style
109 : // change however the presshell of underlying document isn't destroyed and
110 : // the document doesn't get pagehide events. Schedule a document rebind
111 : // to its parent document. Otherwise a document accessible may be lost if
112 : // its outerdoc has being recreated (see bug 862863 for details).
113 0 : if (!mDoc->IsDefunct()) {
114 0 : mDoc->BindChildDocument(child->AsDoc());
115 : }
116 : }
117 :
118 0 : AccessibleWrap::Shutdown();
119 0 : }
120 :
121 : bool
122 0 : OuterDocAccessible::InsertChildAt(uint32_t aIdx, Accessible* aAccessible)
123 : {
124 0 : MOZ_RELEASE_ASSERT(aAccessible->IsDoc(),
125 : "OuterDocAccessible can have a document child only!");
126 :
127 : // We keep showing the old document for a bit after creating the new one,
128 : // and while building the new DOM and frame tree. That's done on purpose
129 : // to avoid weird flashes of default background color.
130 : // The old viewer will be destroyed after the new one is created.
131 : // For a11y, it should be safe to shut down the old document now.
132 0 : if (mChildren.Length())
133 0 : mChildren[0]->Shutdown();
134 :
135 0 : if (!AccessibleWrap::InsertChildAt(0, aAccessible))
136 0 : return false;
137 :
138 : #ifdef A11Y_LOG
139 0 : if (logging::IsEnabled(logging::eDocCreate)) {
140 0 : logging::DocCreate("append document to outerdoc",
141 0 : aAccessible->AsDoc()->DocumentNode());
142 0 : logging::Address("outerdoc", this);
143 : }
144 : #endif
145 :
146 0 : return true;
147 : }
148 :
149 : bool
150 0 : OuterDocAccessible::RemoveChild(Accessible* aAccessible)
151 : {
152 0 : Accessible* child = mChildren.SafeElementAt(0, nullptr);
153 0 : if (child != aAccessible) {
154 0 : NS_ERROR("Wrong child to remove!");
155 0 : return false;
156 : }
157 :
158 : #ifdef A11Y_LOG
159 0 : if (logging::IsEnabled(logging::eDocDestroy)) {
160 0 : logging::DocDestroy("remove document from outerdoc",
161 0 : child->AsDoc()->DocumentNode(), child->AsDoc());
162 0 : logging::Address("outerdoc", this);
163 : }
164 : #endif
165 :
166 0 : bool wasRemoved = AccessibleWrap::RemoveChild(child);
167 :
168 0 : NS_ASSERTION(!mChildren.Length(),
169 : "This child document of outerdoc accessible wasn't removed!");
170 :
171 0 : return wasRemoved;
172 : }
173 :
174 : bool
175 0 : OuterDocAccessible::IsAcceptableChild(nsIContent* aEl) const
176 : {
177 : // outer document accessible doesn't not participate in ordinal tree
178 : // mutations.
179 0 : return false;
180 : }
181 :
182 : #if defined(XP_WIN)
183 :
184 : // On Windows e10s, since we don't cache in the chrome process, these next two
185 : // functions must be implemented so that we properly cross the chrome-to-content
186 : // boundary when traversing.
187 :
188 : uint32_t
189 : OuterDocAccessible::ChildCount() const
190 : {
191 : uint32_t result = mChildren.Length();
192 : if (!result && RemoteChildDoc()) {
193 : result = 1;
194 : }
195 : return result;
196 : }
197 :
198 : Accessible*
199 : OuterDocAccessible::GetChildAt(uint32_t aIndex) const
200 : {
201 : Accessible* result = AccessibleWrap::GetChildAt(aIndex);
202 : if (result || aIndex) {
203 : return result;
204 : }
205 : // If we are asking for child 0 and GetChildAt doesn't return anything, try
206 : // to get the remote child doc and return that instead.
207 : ProxyAccessible* remoteChild = RemoteChildDoc();
208 : if (!remoteChild) {
209 : return nullptr;
210 : }
211 : return WrapperFor(remoteChild);
212 : }
213 :
214 : #endif // defined(XP_WIN)
215 :
216 : DocAccessibleParent*
217 0 : OuterDocAccessible::RemoteChildDoc() const
218 : {
219 0 : dom::TabParent* tab = dom::TabParent::GetFrom(GetContent());
220 0 : if (!tab)
221 0 : return nullptr;
222 :
223 0 : return tab->GetTopLevelDocAccessible();
224 : }
|