OuterDocAccessible.cpp 6.1 KB

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