From ee6e42b6dee44d8628c90750eb93d29b9013766b Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Tue, 12 Jul 2016 23:15:22 -0400 Subject: [PATCH] Bug 1276857 - Shutdown an accessible if cannot be inserted into the tree, r=yzen --- accessible/generic/Accessible-inl.h | 28 ++++++++++++++++++++++++++++ accessible/generic/Accessible.cpp | 1 - accessible/generic/Accessible.h | 12 ++++++------ accessible/generic/DocAccessible.cpp | 11 ++++++++++- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/accessible/generic/Accessible-inl.h b/accessible/generic/Accessible-inl.h index 93017f8b4d05..51e26de47589 100644 --- a/accessible/generic/Accessible-inl.h +++ b/accessible/generic/Accessible-inl.h @@ -11,6 +11,10 @@ #include "ARIAMap.h" #include "nsCoreUtils.h" +#ifdef A11Y_LOG +#include "Logging.h" +#endif + namespace mozilla { namespace a11y { @@ -76,6 +80,30 @@ Accessible::ScrollTo(uint32_t aHow) const nsCoreUtils::ScrollTo(mDoc->PresShell(), mContent, aHow); } +inline bool +Accessible::InsertAfter(Accessible* aNewChild, Accessible* aRefChild) +{ + MOZ_ASSERT(aNewChild, "No new child to insert"); + + if (aRefChild && aRefChild->Parent() != this) { +#ifdef A11Y_LOG + logging::TreeInfo("broken accessible tree", 0, + "parent", this, "prev sibling parent", + aRefChild->Parent(), "child", aNewChild, nullptr); + if (logging::IsEnabled(logging::eVerbose)) { + logging::Tree("TREE", "Document tree", mDoc); + logging::DOMTree("TREE", "DOM document tree", mDoc); + } +#endif + MOZ_ASSERT_UNREACHABLE("Broken accessible tree"); + mDoc->UnbindFromDocument(aNewChild); + return false; + } + + return InsertChildAt(aRefChild ? aRefChild->IndexInParent() + 1 : 0, + aNewChild); +} + } // namespace a11y } // namespace mozilla diff --git a/accessible/generic/Accessible.cpp b/accessible/generic/Accessible.cpp index 49a962315589..fca2fff1eb44 100644 --- a/accessible/generic/Accessible.cpp +++ b/accessible/generic/Accessible.cpp @@ -18,7 +18,6 @@ #include "nsTextEquivUtils.h" #include "DocAccessibleChild.h" #include "EventTree.h" -#include "Logging.h" #include "Relation.h" #include "Role.h" #include "RootAccessible.h" diff --git a/accessible/generic/Accessible.h b/accessible/generic/Accessible.h index 1050387252da..3d7892f91782 100644 --- a/accessible/generic/Accessible.h +++ b/accessible/generic/Accessible.h @@ -393,12 +393,12 @@ public: { return InsertChildAt(mChildren.Length(), aChild); } virtual bool InsertChildAt(uint32_t aIndex, Accessible* aChild); - bool InsertAfter(Accessible* aNewChild, Accessible* aRefChild) - { - MOZ_ASSERT(aNewChild, "No new child to insert"); - return InsertChildAt(aRefChild ? aRefChild->IndexInParent() + 1 : 0, - aNewChild); - } + /** + * Inserts a child after given sibling. If the child cannot be inserted, + * then the child is unbound from the document, and false is returned. Make + * sure to null out any references on the child object as it may be destroyed. + */ + bool InsertAfter(Accessible* aNewChild, Accessible* aRefChild); virtual bool RemoveChild(Accessible* aChild); diff --git a/accessible/generic/DocAccessible.cpp b/accessible/generic/DocAccessible.cpp index b957b044a1fa..d470972a1b15 100644 --- a/accessible/generic/DocAccessible.cpp +++ b/accessible/generic/DocAccessible.cpp @@ -1681,6 +1681,12 @@ public: */ bool Next(); + void Rejected() + { + mChild = nullptr; + mChildBefore = nullptr; + } + private: Accessible* mChild; Accessible* mChildBefore; @@ -1815,6 +1821,7 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer, } MOZ_ASSERT_UNREACHABLE("accessible was rejected"); + iter.Rejected(); } while (iter.Next()); mt.Done(); @@ -1852,7 +1859,9 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer, nsIContent* aNode) if (child) { TreeMutation mt(aContainer); - aContainer->InsertAfter(child, walker.Prev()); + if (!aContainer->InsertAfter(child, walker.Prev())) { + return; + } mt.AfterInsertion(child); mt.Done();