diff options
Diffstat (limited to 'accessible/ipc/DocAccessibleParent.cpp')
-rw-r--r-- | accessible/ipc/DocAccessibleParent.cpp | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/accessible/ipc/DocAccessibleParent.cpp b/accessible/ipc/DocAccessibleParent.cpp new file mode 100644 index 000000000..38b41357e --- /dev/null +++ b/accessible/ipc/DocAccessibleParent.cpp @@ -0,0 +1,181 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "DocAccessibleParent.h" +#include "nsAutoPtr.h" +#include "mozilla/a11y/Platform.h" +#include "ProxyAccessible.h" + +namespace mozilla { +namespace a11y { + +bool +DocAccessibleParent::RecvShowEvent(const ShowEventData& aData) +{ + if (mShutdown) + return true; + + if (aData.NewTree().IsEmpty()) { + NS_ERROR("no children being added"); + return false; + } + + ProxyAccessible* parent = nullptr; + if (aData.ID()) { + ProxyEntry* e = mAccessibles.GetEntry(aData.ID()); + if (e) + parent = e->mProxy; + } else { + parent = this; + } + + // XXX This should really never happen, but sometimes we fail to fire the + // required show events. + if (!parent) { + NS_ERROR("adding child to unknown accessible"); + return false; + } + + uint32_t newChildIdx = aData.Idx(); + if (newChildIdx > parent->ChildrenCount()) { + NS_ERROR("invalid index to add child at"); + return false; + } + + uint32_t consumed = AddSubtree(parent, aData.NewTree(), 0, newChildIdx); + MOZ_ASSERT(consumed == aData.NewTree().Length()); +#ifdef DEBUG + for (uint32_t i = 0; i < consumed; i++) { + uint64_t id = aData.NewTree()[i].ID(); + MOZ_ASSERT(mAccessibles.GetEntry(id)); + } +#endif + + return consumed != 0; +} + +uint32_t +DocAccessibleParent::AddSubtree(ProxyAccessible* aParent, + const nsTArray<a11y::AccessibleData>& aNewTree, + uint32_t aIdx, uint32_t aIdxInParent) +{ + if (aNewTree.Length() <= aIdx) { + NS_ERROR("bad index in serialized tree!"); + return 0; + } + + const AccessibleData& newChild = aNewTree[aIdx]; + if (newChild.Role() > roles::LAST_ROLE) { + NS_ERROR("invalid role"); + return 0; + } + + auto role = static_cast<a11y::role>(newChild.Role()); + ProxyAccessible* newProxy = + new ProxyAccessible(newChild.ID(), aParent, this, role); + aParent->AddChildAt(aIdxInParent, newProxy); + mAccessibles.PutEntry(newChild.ID())->mProxy = newProxy; + ProxyCreated(newProxy, newChild.Interfaces()); + + uint32_t accessibles = 1; + uint32_t kids = newChild.ChildrenCount(); + for (uint32_t i = 0; i < kids; i++) { + uint32_t consumed = AddSubtree(newProxy, aNewTree, aIdx + accessibles, i); + if (!consumed) + return 0; + + accessibles += consumed; + } + + MOZ_ASSERT(newProxy->ChildrenCount() == kids); + + return accessibles; +} + +bool +DocAccessibleParent::RecvHideEvent(const uint64_t& aRootID) +{ + if (mShutdown) + return true; + + ProxyEntry* rootEntry = mAccessibles.GetEntry(aRootID); + if (!rootEntry) { + NS_ERROR("invalid root being removed!"); + return true; + } + + ProxyAccessible* root = rootEntry->mProxy; + if (!root) { + NS_ERROR("invalid root being removed!"); + return true; + } + + ProxyAccessible* parent = root->Parent(); + parent->RemoveChild(root); + root->Shutdown(); + + return true; +} + +bool +DocAccessibleParent::RecvEvent(const uint64_t& aID, const uint32_t& aEventType) +{ + if (!aID) { + ProxyEvent(this, aEventType); + return true; + } + + ProxyEntry* e = mAccessibles.GetEntry(aID); + if (!e) { + NS_ERROR("no proxy for event!"); + return true; + } + + ProxyEvent(e->mProxy, aEventType); + return true; +} +bool +DocAccessibleParent::AddChildDoc(DocAccessibleParent* aChildDoc, + uint64_t aParentID) +{ + ProxyAccessible* outerDoc = mAccessibles.GetEntry(aParentID)->mProxy; + if (!outerDoc) + return false; + + aChildDoc->mParent = outerDoc; + outerDoc->SetChildDoc(aChildDoc); + mChildDocs.AppendElement(aChildDoc); + aChildDoc->mParentDoc = this; + ProxyCreated(aChildDoc, 0); + return true; +} + +PLDHashOperator +DocAccessibleParent::ShutdownAccessibles(ProxyEntry* entry, void*) +{ + ProxyDestroyed(entry->mProxy); + return PL_DHASH_REMOVE; +} + +void +DocAccessibleParent::Destroy() +{ + NS_ASSERTION(mChildDocs.IsEmpty(), + "why weren't the child docs destroyed already?"); + MOZ_ASSERT(!mShutdown); + mShutdown = true; + + uint32_t childDocCount = mChildDocs.Length(); + for (uint32_t i = childDocCount - 1; i < childDocCount; i--) + mChildDocs[i]->Destroy(); + + mAccessibles.EnumerateEntries(ShutdownAccessibles, nullptr); + ProxyDestroyed(this); + mParentDoc ? mParentDoc->RemoveChildDoc(this) + : GetAccService()->RemoteDocShutdown(this); +} +} +} |