ProxyAccessibleBase.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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 "DocAccessible.h"
  6. #include "mozilla/a11y/DocAccessibleParent.h"
  7. #include "mozilla/a11y/DocManager.h"
  8. #include "mozilla/a11y/Platform.h"
  9. #include "mozilla/a11y/ProxyAccessibleBase.h"
  10. #include "mozilla/a11y/ProxyAccessible.h"
  11. #include "mozilla/a11y/Role.h"
  12. #include "mozilla/dom/Element.h"
  13. #include "mozilla/dom/TabParent.h"
  14. #include "mozilla/Unused.h"
  15. #include "RelationType.h"
  16. #include "xpcAccessibleDocument.h"
  17. namespace mozilla {
  18. namespace a11y {
  19. template <class Derived>
  20. void
  21. ProxyAccessibleBase<Derived>::Shutdown()
  22. {
  23. MOZ_DIAGNOSTIC_ASSERT(!IsDoc());
  24. NS_ASSERTION(!mOuterDoc, "Why do we still have a child doc?");
  25. xpcAccessibleDocument* xpcDoc =
  26. GetAccService()->GetCachedXPCDocument(Document());
  27. if (xpcDoc) {
  28. xpcDoc->NotifyOfShutdown(static_cast<Derived*>(this));
  29. }
  30. // XXX Ideally this wouldn't be necessary, but it seems OuterDoc accessibles
  31. // can be destroyed before the doc they own.
  32. if (!mOuterDoc) {
  33. uint32_t childCount = mChildren.Length();
  34. for (uint32_t idx = 0; idx < childCount; idx++)
  35. mChildren[idx]->Shutdown();
  36. } else {
  37. if (mChildren.Length() != 1)
  38. MOZ_CRASH("outer doc doesn't own adoc!");
  39. mChildren[0]->AsDoc()->Unbind();
  40. }
  41. mChildren.Clear();
  42. ProxyDestroyed(static_cast<Derived*>(this));
  43. mDoc->RemoveAccessible(static_cast<Derived*>(this));
  44. }
  45. template <class Derived>
  46. void
  47. ProxyAccessibleBase<Derived>::SetChildDoc(DocAccessibleParent* aChildDoc)
  48. {
  49. // DocAccessibleParent::AddChildDoc tolerates replacing one document with
  50. // another. We must reflect that here.
  51. MOZ_ASSERT(aChildDoc);
  52. MOZ_ASSERT(mChildren.Length() <= 1);
  53. if (mChildren.IsEmpty()) {
  54. mChildren.AppendElement(aChildDoc);
  55. } else {
  56. mChildren.ReplaceElementAt(0, aChildDoc);
  57. }
  58. mOuterDoc = true;
  59. }
  60. template <class Derived>
  61. void
  62. ProxyAccessibleBase<Derived>::ClearChildDoc(DocAccessibleParent* aChildDoc)
  63. {
  64. MOZ_ASSERT(aChildDoc);
  65. // This is possible if we're replacing one document with another: Doc 1
  66. // has not had a chance to remove itself, but was already replaced by Doc 2
  67. // in SetChildDoc(). This could result in two subsequent calls to
  68. // ClearChildDoc() even though mChildren.Length() == 1.
  69. MOZ_ASSERT(mChildren.Length() <= 1);
  70. if (mChildren.RemoveElement(aChildDoc)) {
  71. mOuterDoc = false;
  72. }
  73. }
  74. template <class Derived>
  75. bool
  76. ProxyAccessibleBase<Derived>::MustPruneChildren() const
  77. {
  78. // this is the equivalent to nsAccUtils::MustPrune for proxies and should be
  79. // kept in sync with that.
  80. if (mRole != roles::MENUITEM && mRole != roles::COMBOBOX_OPTION
  81. && mRole != roles::OPTION && mRole != roles::ENTRY
  82. && mRole != roles::FLAT_EQUATION && mRole != roles::PASSWORD_TEXT
  83. && mRole != roles::PUSHBUTTON && mRole != roles::TOGGLE_BUTTON
  84. && mRole != roles::GRAPHIC && mRole != roles::SLIDER
  85. && mRole != roles::PROGRESSBAR && mRole != roles::SEPARATOR)
  86. return false;
  87. if (mChildren.Length() != 1)
  88. return false;
  89. return mChildren[0]->Role() == roles::TEXT_LEAF
  90. || mChildren[0]->Role() == roles::STATICTEXT;
  91. }
  92. template <class Derived>
  93. uint32_t
  94. ProxyAccessibleBase<Derived>::EmbeddedChildCount() const
  95. {
  96. size_t count = 0, kids = mChildren.Length();
  97. for (size_t i = 0; i < kids; i++) {
  98. if (mChildren[i]->IsEmbeddedObject()) {
  99. count++;
  100. }
  101. }
  102. return count;
  103. }
  104. template <class Derived>
  105. int32_t
  106. ProxyAccessibleBase<Derived>::IndexOfEmbeddedChild(const Derived* aChild)
  107. {
  108. size_t index = 0, kids = mChildren.Length();
  109. for (size_t i = 0; i < kids; i++) {
  110. if (mChildren[i]->IsEmbeddedObject()) {
  111. if (mChildren[i] == aChild) {
  112. return index;
  113. }
  114. index++;
  115. }
  116. }
  117. return -1;
  118. }
  119. template <class Derived>
  120. Derived*
  121. ProxyAccessibleBase<Derived>::EmbeddedChildAt(size_t aChildIdx)
  122. {
  123. size_t index = 0, kids = mChildren.Length();
  124. for (size_t i = 0; i < kids; i++) {
  125. if (!mChildren[i]->IsEmbeddedObject()) {
  126. continue;
  127. }
  128. if (index == aChildIdx) {
  129. return mChildren[i];
  130. }
  131. index++;
  132. }
  133. return nullptr;
  134. }
  135. template <class Derived>
  136. Accessible*
  137. ProxyAccessibleBase<Derived>::OuterDocOfRemoteBrowser() const
  138. {
  139. auto tab = static_cast<dom::TabParent*>(mDoc->Manager());
  140. dom::Element* frame = tab->GetOwnerElement();
  141. NS_ASSERTION(frame, "why isn't the tab in a frame!");
  142. if (!frame)
  143. return nullptr;
  144. DocAccessible* chromeDoc = GetExistingDocAccessible(frame->OwnerDoc());
  145. return chromeDoc ? chromeDoc->GetAccessible(frame) : nullptr;
  146. }
  147. template class ProxyAccessibleBase<ProxyAccessible>;
  148. } // namespace a11y
  149. } // namespace mozilla