/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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 void ProxyAccessibleBase::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(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(this)); mDoc->RemoveAccessible(static_cast(this)); } template void ProxyAccessibleBase::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 void ProxyAccessibleBase::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 bool ProxyAccessibleBase::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 uint32_t ProxyAccessibleBase::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 int32_t ProxyAccessibleBase::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 Derived* ProxyAccessibleBase::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 Accessible* ProxyAccessibleBase::OuterDocOfRemoteBrowser() const { auto tab = static_cast(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; } // namespace a11y } // namespace mozilla