diff options
Diffstat (limited to 'accessible/ipc/ProxyAccessibleBase.cpp')
-rw-r--r-- | accessible/ipc/ProxyAccessibleBase.cpp | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/accessible/ipc/ProxyAccessibleBase.cpp b/accessible/ipc/ProxyAccessibleBase.cpp new file mode 100644 index 0000000000..8f1a2b7eda --- /dev/null +++ b/accessible/ipc/ProxyAccessibleBase.cpp @@ -0,0 +1,175 @@ +/* -*- 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 "DocAccessible.h" +#include "mozilla/a11y/DocAccessibleParent.h" +#include "mozilla/a11y/DocManager.h" +#include "mozilla/a11y/Platform.h" +#include "mozilla/a11y/ProxyAccessibleBase.h" +#include "mozilla/a11y/ProxyAccessible.h" +#include "mozilla/a11y/Role.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/TabParent.h" +#include "mozilla/Unused.h" +#include "RelationType.h" +#include "xpcAccessibleDocument.h" + +namespace mozilla { +namespace a11y { + +template <class Derived> +void +ProxyAccessibleBase<Derived>::Shutdown() +{ + MOZ_DIAGNOSTIC_ASSERT(!IsDoc()); + NS_ASSERTION(!mOuterDoc, "Why do we still have a child doc?"); + xpcAccessibleDocument* xpcDoc = + GetAccService()->GetCachedXPCDocument(Document()); + if (xpcDoc) { + xpcDoc->NotifyOfShutdown(static_cast<Derived*>(this)); + } + + // XXX Ideally this wouldn't be necessary, but it seems OuterDoc accessibles + // can be destroyed before the doc they own. + if (!mOuterDoc) { + uint32_t childCount = mChildren.Length(); + for (uint32_t idx = 0; idx < childCount; idx++) + mChildren[idx]->Shutdown(); + } else { + if (mChildren.Length() != 1) + MOZ_CRASH("outer doc doesn't own adoc!"); + + mChildren[0]->AsDoc()->Unbind(); + } + + mChildren.Clear(); + ProxyDestroyed(static_cast<Derived*>(this)); + mDoc->RemoveAccessible(static_cast<Derived*>(this)); +} + +template <class Derived> +void +ProxyAccessibleBase<Derived>::SetChildDoc(DocAccessibleParent* aChildDoc) +{ + // DocAccessibleParent::AddChildDoc tolerates replacing one document with + // another. We must reflect that here. + MOZ_ASSERT(aChildDoc); + MOZ_ASSERT(mChildren.Length() <= 1); + if (mChildren.IsEmpty()) { + mChildren.AppendElement(aChildDoc); + } else { + mChildren.ReplaceElementAt(0, aChildDoc); + } + mOuterDoc = true; +} + +template <class Derived> +void +ProxyAccessibleBase<Derived>::ClearChildDoc(DocAccessibleParent* aChildDoc) +{ + MOZ_ASSERT(aChildDoc); + // This is possible if we're replacing one document with another: Doc 1 + // has not had a chance to remove itself, but was already replaced by Doc 2 + // in SetChildDoc(). This could result in two subsequent calls to + // ClearChildDoc() even though mChildren.Length() == 1. + MOZ_ASSERT(mChildren.Length() <= 1); + if (mChildren.RemoveElement(aChildDoc)) { + mOuterDoc = false; + } +} + +template <class Derived> +bool +ProxyAccessibleBase<Derived>::MustPruneChildren() const +{ + // this is the equivalent to nsAccUtils::MustPrune for proxies and should be + // kept in sync with that. + if (mRole != roles::MENUITEM && mRole != roles::COMBOBOX_OPTION + && mRole != roles::OPTION && mRole != roles::ENTRY + && mRole != roles::FLAT_EQUATION && mRole != roles::PASSWORD_TEXT + && mRole != roles::PUSHBUTTON && mRole != roles::TOGGLE_BUTTON + && mRole != roles::GRAPHIC && mRole != roles::SLIDER + && mRole != roles::PROGRESSBAR && mRole != roles::SEPARATOR) + return false; + + if (mChildren.Length() != 1) + return false; + + return mChildren[0]->Role() == roles::TEXT_LEAF + || mChildren[0]->Role() == roles::STATICTEXT; +} + +template <class Derived> +uint32_t +ProxyAccessibleBase<Derived>::EmbeddedChildCount() const +{ + size_t count = 0, kids = mChildren.Length(); + for (size_t i = 0; i < kids; i++) { + if (mChildren[i]->IsEmbeddedObject()) { + count++; + } + } + + return count; +} + +template <class Derived> +int32_t +ProxyAccessibleBase<Derived>::IndexOfEmbeddedChild(const Derived* aChild) +{ + size_t index = 0, kids = mChildren.Length(); + for (size_t i = 0; i < kids; i++) { + if (mChildren[i]->IsEmbeddedObject()) { + if (mChildren[i] == aChild) { + return index; + } + + index++; + } + } + + return -1; +} + +template <class Derived> +Derived* +ProxyAccessibleBase<Derived>::EmbeddedChildAt(size_t aChildIdx) +{ + size_t index = 0, kids = mChildren.Length(); + for (size_t i = 0; i < kids; i++) { + if (!mChildren[i]->IsEmbeddedObject()) { + continue; + } + + if (index == aChildIdx) { + return mChildren[i]; + } + + index++; + } + + return nullptr; +} + +template <class Derived> +Accessible* +ProxyAccessibleBase<Derived>::OuterDocOfRemoteBrowser() const +{ + auto tab = static_cast<dom::TabParent*>(mDoc->Manager()); + dom::Element* frame = tab->GetOwnerElement(); + NS_ASSERTION(frame, "why isn't the tab in a frame!"); + if (!frame) + return nullptr; + + DocAccessible* chromeDoc = GetExistingDocAccessible(frame->OwnerDoc()); + + return chromeDoc ? chromeDoc->GetAccessible(frame) : nullptr; +} + +template class ProxyAccessibleBase<ProxyAccessible>; + +} // namespace a11y +} // namespace mozilla |