diff options
Diffstat (limited to 'accessible/ipc')
28 files changed, 7163 insertions, 0 deletions
diff --git a/accessible/ipc/DocAccessibleChildBase.cpp b/accessible/ipc/DocAccessibleChildBase.cpp new file mode 100644 index 0000000000..6a0ad9b7db --- /dev/null +++ b/accessible/ipc/DocAccessibleChildBase.cpp @@ -0,0 +1,97 @@ +/* -*- 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 "mozilla/a11y/DocAccessibleChildBase.h" +#include "mozilla/a11y/ProxyAccessible.h" + +#include "Accessible-inl.h" + +namespace mozilla { +namespace a11y { + +/* static */ uint32_t +DocAccessibleChildBase::InterfacesFor(Accessible* aAcc) +{ + uint32_t interfaces = 0; + if (aAcc->IsHyperText() && aAcc->AsHyperText()->IsTextRole()) + interfaces |= Interfaces::HYPERTEXT; + + if (aAcc->IsLink()) + interfaces |= Interfaces::HYPERLINK; + + if (aAcc->HasNumericValue()) + interfaces |= Interfaces::VALUE; + + if (aAcc->IsImage()) + interfaces |= Interfaces::IMAGE; + + if (aAcc->IsTable()) { + interfaces |= Interfaces::TABLE; + } + + if (aAcc->IsTableCell()) + interfaces |= Interfaces::TABLECELL; + + if (aAcc->IsDoc()) + interfaces |= Interfaces::DOCUMENT; + + if (aAcc->IsSelect()) { + interfaces |= Interfaces::SELECTION; + } + + if (aAcc->ActionCount()) { + interfaces |= Interfaces::ACTION; + } + + return interfaces; +} + +/* static */ void +DocAccessibleChildBase::SerializeTree(Accessible* aRoot, + nsTArray<AccessibleData>& aTree) +{ + uint64_t id = reinterpret_cast<uint64_t>(aRoot->UniqueID()); +#if defined(XP_WIN) + int32_t msaaId = AccessibleWrap::GetChildIDFor(aRoot); +#endif + uint32_t role = aRoot->Role(); + uint32_t childCount = aRoot->ChildCount(); + uint32_t interfaces = InterfacesFor(aRoot); + + // OuterDocAccessibles are special because we don't want to serialize the + // child doc here, we'll call PDocAccessibleConstructor in + // NotificationController. + MOZ_ASSERT(!aRoot->IsDoc(), "documents shouldn't be serialized"); + if (aRoot->IsOuterDoc()) { + childCount = 0; + } + +#if defined(XP_WIN) + aTree.AppendElement(AccessibleData(id, msaaId, role, childCount, interfaces)); +#else + aTree.AppendElement(AccessibleData(id, role, childCount, interfaces)); +#endif + + for (uint32_t i = 0; i < childCount; i++) { + SerializeTree(aRoot->GetChildAt(i), aTree); + } +} + +void +DocAccessibleChildBase::ShowEvent(AccShowEvent* aShowEvent) +{ + Accessible* parent = aShowEvent->Parent(); + uint64_t parentID = parent->IsDoc() ? 0 : reinterpret_cast<uint64_t>(parent->UniqueID()); + uint32_t idxInParent = aShowEvent->GetAccessible()->IndexInParent(); + nsTArray<AccessibleData> shownTree; + ShowEventData data(parentID, idxInParent, shownTree); + SerializeTree(aShowEvent->GetAccessible(), data.NewTree()); + MaybeSendShowEvent(data, aShowEvent->IsFromUserInput()); +} + +} // namespace a11y +} // namespace mozilla + diff --git a/accessible/ipc/DocAccessibleChildBase.h b/accessible/ipc/DocAccessibleChildBase.h new file mode 100644 index 0000000000..b8a8bfde1d --- /dev/null +++ b/accessible/ipc/DocAccessibleChildBase.h @@ -0,0 +1,81 @@ +/* -*- 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/. */ + +#ifndef mozilla_a11y_DocAccessibleChildBase_h +#define mozilla_a11y_DocAccessibleChildBase_h + +#include "mozilla/a11y/DocAccessible.h" +#include "mozilla/a11y/PDocAccessibleChild.h" +#include "mozilla/Unused.h" +#include "nsISupportsImpl.h" + +namespace mozilla { +namespace a11y { + +class Accessible; +class AccShowEvent; + +class DocAccessibleChildBase : public PDocAccessibleChild +{ +public: + explicit DocAccessibleChildBase(DocAccessible* aDoc) + : mDoc(aDoc) + { + MOZ_COUNT_CTOR(DocAccessibleChildBase); + } + + ~DocAccessibleChildBase() + { + // Shutdown() should have been called, but maybe it isn't if the process is + // killed? + MOZ_ASSERT(!mDoc); + if (mDoc) { + mDoc->SetIPCDoc(nullptr); + } + + MOZ_COUNT_DTOR(DocAccessibleChildBase); + } + + virtual void Shutdown() + { + DetachDocument(); + SendShutdown(); + } + + void ShowEvent(AccShowEvent* aShowEvent); + + virtual void ActorDestroy(ActorDestroyReason) override + { + if (!mDoc) { + return; + } + + mDoc->SetIPCDoc(nullptr); + mDoc = nullptr; + } + +protected: + static uint32_t InterfacesFor(Accessible* aAcc); + static void SerializeTree(Accessible* aRoot, nsTArray<AccessibleData>& aTree); + + virtual void MaybeSendShowEvent(ShowEventData& aData, bool aFromUser) + { Unused << SendShowEvent(aData, aFromUser); } + + void DetachDocument() + { + if (mDoc) { + mDoc->SetIPCDoc(nullptr); + mDoc = nullptr; + } + } + + DocAccessible* mDoc; +}; + +} // namespace a11y +} // namespace mozilla + +#endif // mozilla_a11y_DocAccessibleChildBase_h diff --git a/accessible/ipc/DocAccessibleParent.cpp b/accessible/ipc/DocAccessibleParent.cpp new file mode 100644 index 0000000000..0e9dfc0806 --- /dev/null +++ b/accessible/ipc/DocAccessibleParent.cpp @@ -0,0 +1,526 @@ +/* -*- 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 "mozilla/a11y/Platform.h" +#include "mozilla/dom/TabParent.h" +#include "xpcAccessibleDocument.h" +#include "xpcAccEvents.h" +#include "nsAccUtils.h" +#include "nsCoreUtils.h" + +namespace mozilla { +namespace a11y { + +bool +DocAccessibleParent::RecvShowEvent(const ShowEventData& aData, + const bool& aFromUser) +{ + if (mShutdown) + return true; + + MOZ_DIAGNOSTIC_ASSERT(CheckDocTree()); + + if (aData.NewTree().IsEmpty()) { + NS_ERROR("no children being added"); + return false; + } + + ProxyAccessible* parent = GetAccessible(aData.ID()); + + // 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 true; + } + + uint32_t newChildIdx = aData.Idx(); + if (newChildIdx > parent->ChildrenCount()) { + NS_ERROR("invalid index to add child at"); + return true; + } + + uint32_t consumed = AddSubtree(parent, aData.NewTree(), 0, newChildIdx); + MOZ_ASSERT(consumed == aData.NewTree().Length()); + + // XXX This shouldn't happen, but if we failed to add children then the below + // is pointless and can crash. + if (!consumed) { + return true; + } + +#ifdef DEBUG + for (uint32_t i = 0; i < consumed; i++) { + uint64_t id = aData.NewTree()[i].ID(); + MOZ_ASSERT(mAccessibles.GetEntry(id)); + } +#endif + + MOZ_DIAGNOSTIC_ASSERT(CheckDocTree()); + + ProxyAccessible* target = parent->ChildAt(newChildIdx); + ProxyShowHideEvent(target, parent, true, aFromUser); + + if (!nsCoreUtils::AccEventObserversExist()) { + return true; + } + + uint32_t type = nsIAccessibleEvent::EVENT_SHOW; + xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(target); + xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this); + nsIDOMNode* node = nullptr; + RefPtr<xpcAccEvent> event = new xpcAccEvent(type, xpcAcc, doc, node, + aFromUser); + nsCoreUtils::DispatchAccEvent(Move(event)); + + return true; +} + +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; + } + + if (mAccessibles.Contains(newChild.ID())) { + NS_ERROR("ID already in use"); + return 0; + } + + auto role = static_cast<a11y::role>(newChild.Role()); + + ProxyAccessible* newProxy = + new ProxyAccessible(newChild.ID(), aParent, this, role, + newChild.Interfaces()); + + aParent->AddChildAt(aIdxInParent, newProxy); + mAccessibles.PutEntry(newChild.ID())->mProxy = newProxy; + ProxyCreated(newProxy, newChild.Interfaces()); + +#if defined(XP_WIN) + WrapperFor(newProxy)->SetID(newChild.MsaaID()); +#endif + + 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, + const bool& aFromUser) +{ + if (mShutdown) + return true; + + MOZ_DIAGNOSTIC_ASSERT(CheckDocTree()); + + // We shouldn't actually need this because mAccessibles shouldn't have an + // entry for the document itself, but it doesn't hurt to be explicit. + if (!aRootID) { + NS_ERROR("trying to hide entire document?"); + return false; + } + + 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(); + ProxyShowHideEvent(root, parent, false, aFromUser); + + RefPtr<xpcAccHideEvent> event = nullptr; + if (nsCoreUtils::AccEventObserversExist()) { + uint32_t type = nsIAccessibleEvent::EVENT_HIDE; + xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(root); + xpcAccessibleGeneric* xpcParent = GetXPCAccessible(parent); + ProxyAccessible* next = root->NextSibling(); + xpcAccessibleGeneric* xpcNext = next ? GetXPCAccessible(next) : nullptr; + ProxyAccessible* prev = root->PrevSibling(); + xpcAccessibleGeneric* xpcPrev = prev ? GetXPCAccessible(prev) : nullptr; + xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this); + nsIDOMNode* node = nullptr; + event = new xpcAccHideEvent(type, xpcAcc, doc, node, aFromUser, xpcParent, + xpcNext, xpcPrev); + } + + parent->RemoveChild(root); + root->Shutdown(); + + MOZ_DIAGNOSTIC_ASSERT(CheckDocTree()); + + if (event) { + nsCoreUtils::DispatchAccEvent(Move(event)); + } + + return true; +} + +bool +DocAccessibleParent::RecvEvent(const uint64_t& aID, const uint32_t& aEventType) +{ + ProxyAccessible* proxy = GetAccessible(aID); + if (!proxy) { + NS_ERROR("no proxy for event!"); + return true; + } + + ProxyEvent(proxy, aEventType); + + if (!nsCoreUtils::AccEventObserversExist()) { + return true; + } + + xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(proxy); + xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this); + nsIDOMNode* node = nullptr; + bool fromUser = true; // XXX fix me + RefPtr<xpcAccEvent> event = new xpcAccEvent(aEventType, xpcAcc, doc, node, + fromUser); + nsCoreUtils::DispatchAccEvent(Move(event)); + + return true; +} + +bool +DocAccessibleParent::RecvStateChangeEvent(const uint64_t& aID, + const uint64_t& aState, + const bool& aEnabled) +{ + ProxyAccessible* target = GetAccessible(aID); + if (!target) { + NS_ERROR("we don't know about the target of a state change event!"); + return true; + } + + ProxyStateChangeEvent(target, aState, aEnabled); + + if (!nsCoreUtils::AccEventObserversExist()) { + return true; + } + + xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(target); + xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this); + uint32_t type = nsIAccessibleEvent::EVENT_STATE_CHANGE; + bool extra; + uint32_t state = nsAccUtils::To32States(aState, &extra); + bool fromUser = true; // XXX fix this + nsIDOMNode* node = nullptr; // XXX can we do better? + RefPtr<xpcAccStateChangeEvent> event = + new xpcAccStateChangeEvent(type, xpcAcc, doc, node, fromUser, state, extra, + aEnabled); + nsCoreUtils::DispatchAccEvent(Move(event)); + + return true; +} + +bool +DocAccessibleParent::RecvCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset) +{ + ProxyAccessible* proxy = GetAccessible(aID); + if (!proxy) { + NS_ERROR("unknown caret move event target!"); + return true; + } + + ProxyCaretMoveEvent(proxy, aOffset); + + if (!nsCoreUtils::AccEventObserversExist()) { + return true; + } + + xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(proxy); + xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this); + nsIDOMNode* node = nullptr; + bool fromUser = true; // XXX fix me + uint32_t type = nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED; + RefPtr<xpcAccCaretMoveEvent> event = + new xpcAccCaretMoveEvent(type, xpcAcc, doc, node, fromUser, aOffset); + nsCoreUtils::DispatchAccEvent(Move(event)); + + return true; +} + +bool +DocAccessibleParent::RecvTextChangeEvent(const uint64_t& aID, + const nsString& aStr, + const int32_t& aStart, + const uint32_t& aLen, + const bool& aIsInsert, + const bool& aFromUser) +{ + ProxyAccessible* target = GetAccessible(aID); + if (!target) { + NS_ERROR("text change event target is unknown!"); + return true; + } + + ProxyTextChangeEvent(target, aStr, aStart, aLen, aIsInsert, aFromUser); + + if (!nsCoreUtils::AccEventObserversExist()) { + return true; + } + + xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(target); + xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this); + uint32_t type = aIsInsert ? nsIAccessibleEvent::EVENT_TEXT_INSERTED : + nsIAccessibleEvent::EVENT_TEXT_REMOVED; + nsIDOMNode* node = nullptr; + RefPtr<xpcAccTextChangeEvent> event = + new xpcAccTextChangeEvent(type, xpcAcc, doc, node, aFromUser, aStart, aLen, + aIsInsert, aStr); + nsCoreUtils::DispatchAccEvent(Move(event)); + + return true; +} + +bool +DocAccessibleParent::RecvSelectionEvent(const uint64_t& aID, + const uint64_t& aWidgetID, + const uint32_t& aType) +{ + ProxyAccessible* target = GetAccessible(aID); + ProxyAccessible* widget = GetAccessible(aWidgetID); + if (!target || !widget) { + NS_ERROR("invalid id in selection event"); + return true; + } + + ProxySelectionEvent(target, widget, aType); + if (!nsCoreUtils::AccEventObserversExist()) { + return true; + } + xpcAccessibleGeneric* xpcTarget = GetXPCAccessible(target); + xpcAccessibleDocument* xpcDoc = GetAccService()->GetXPCDocument(this); + RefPtr<xpcAccEvent> event = new xpcAccEvent(aType, xpcTarget, xpcDoc, + nullptr, false); + nsCoreUtils::DispatchAccEvent(Move(event)); + + return true; +} + +bool +DocAccessibleParent::RecvRoleChangedEvent(const uint32_t& aRole) +{ + if (aRole >= roles::LAST_ROLE) { + NS_ERROR("child sent bad role in RoleChangedEvent"); + return false; + } + + mRole = static_cast<a11y::role>(aRole); + return true; +} + +bool +DocAccessibleParent::RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID) +{ + // One document should never directly be the child of another. + // We should always have at least an outer doc accessible in between. + MOZ_ASSERT(aID); + if (!aID) + return false; + + MOZ_DIAGNOSTIC_ASSERT(CheckDocTree()); + + auto childDoc = static_cast<DocAccessibleParent*>(aChildDoc); + childDoc->Unbind(); + bool result = AddChildDoc(childDoc, aID, false); + MOZ_ASSERT(result); + MOZ_DIAGNOSTIC_ASSERT(CheckDocTree()); + return result; +} + +bool +DocAccessibleParent::AddChildDoc(DocAccessibleParent* aChildDoc, + uint64_t aParentID, bool aCreating) +{ + // We do not use GetAccessible here because we want to be sure to not get the + // document it self. + ProxyEntry* e = mAccessibles.GetEntry(aParentID); + if (!e) + return false; + + ProxyAccessible* outerDoc = e->mProxy; + MOZ_ASSERT(outerDoc); + + // OuterDocAccessibles are expected to only have a document as a child. + // However for compatibility we tolerate replacing one document with another + // here. + if (outerDoc->ChildrenCount() > 1 || + (outerDoc->ChildrenCount() == 1 && !outerDoc->ChildAt(0)->IsDoc())) { + return false; + } + + aChildDoc->mParent = outerDoc; + outerDoc->SetChildDoc(aChildDoc); + mChildDocs.AppendElement(aChildDoc); + aChildDoc->mParentDoc = this; + + if (aCreating) { + ProxyCreated(aChildDoc, Interfaces::DOCUMENT | Interfaces::HYPERTEXT); + } + + return true; +} + +bool +DocAccessibleParent::RecvShutdown() +{ + Destroy(); + + if (!static_cast<dom::TabParent*>(Manager())->IsDestroyed()) { + return PDocAccessibleParent::Send__delete__(this); + } + + return true; +} + +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(); + + for (auto iter = mAccessibles.Iter(); !iter.Done(); iter.Next()) { + MOZ_ASSERT(iter.Get()->mProxy != this); + ProxyDestroyed(iter.Get()->mProxy); + iter.Remove(); + } + + DocManager::NotifyOfRemoteDocShutdown(this); + ProxyDestroyed(this); + if (mParentDoc) + mParentDoc->RemoveChildDoc(this); + else if (IsTopLevel()) + GetAccService()->RemoteDocShutdown(this); +} + +bool +DocAccessibleParent::CheckDocTree() const +{ + size_t childDocs = mChildDocs.Length(); + for (size_t i = 0; i < childDocs; i++) { + if (!mChildDocs[i] || mChildDocs[i]->mParentDoc != this) + return false; + + if (!mChildDocs[i]->CheckDocTree()) { + return false; + } + } + + return true; +} + +xpcAccessibleGeneric* +DocAccessibleParent::GetXPCAccessible(ProxyAccessible* aProxy) +{ + xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this); + MOZ_ASSERT(doc); + + return doc->GetXPCAccessible(aProxy); +} + +#if defined(XP_WIN) +/** + * @param aCOMProxy COM Proxy to the document in the content process. + */ +void +DocAccessibleParent::SetCOMProxy(const RefPtr<IAccessible>& aCOMProxy) +{ + SetCOMInterface(aCOMProxy); + + // Make sure that we're not racing with a tab shutdown + auto tab = static_cast<dom::TabParent*>(Manager()); + MOZ_ASSERT(tab); + if (tab->IsDestroyed()) { + return; + } + + Accessible* outerDoc = OuterDocOfRemoteBrowser(); + MOZ_ASSERT(outerDoc); + + IAccessible* rawNative = nullptr; + if (outerDoc) { + outerDoc->GetNativeInterface((void**) &rawNative); + MOZ_ASSERT(rawNative); + } + + IAccessibleHolder::COMPtrType ptr(rawNative); + IAccessibleHolder holder(Move(ptr)); + Unused << SendParentCOMProxy(holder); +} + +bool +DocAccessibleParent::RecvGetWindowedPluginIAccessible( + const WindowsHandle& aHwnd, IAccessibleHolder* aPluginCOMProxy) +{ +#if defined(MOZ_CONTENT_SANDBOX) + // We don't actually want the accessible object for aHwnd, but rather the + // one that belongs to its child (see HTMLWin32ObjectAccessible). + HWND childWnd = ::GetWindow(reinterpret_cast<HWND>(aHwnd), GW_CHILD); + if (!childWnd) { + // We're seeing this in the wild - the plugin is windowed but we no longer + // have a window. + return true; + } + + IAccessible* rawAccPlugin = nullptr; + HRESULT hr = ::AccessibleObjectFromWindow(childWnd, OBJID_WINDOW, + IID_IAccessible, + (void**)&rawAccPlugin); + if (FAILED(hr)) { + // This might happen if the plugin doesn't handle WM_GETOBJECT properly. + // We should not consider that a failure. + return true; + } + + aPluginCOMProxy->Set(IAccessibleHolder::COMPtrType(rawAccPlugin)); + + return true; +#else + return false; +#endif +} + +#endif // defined(XP_WIN) + +} // a11y +} // mozilla diff --git a/accessible/ipc/DocAccessibleParent.h b/accessible/ipc/DocAccessibleParent.h new file mode 100644 index 0000000000..3686e8a2f2 --- /dev/null +++ b/accessible/ipc/DocAccessibleParent.h @@ -0,0 +1,198 @@ +/* -*- 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/. */ + +#ifndef mozilla_a11y_DocAccessibleParent_h +#define mozilla_a11y_DocAccessibleParent_h + +#include "nsAccessibilityService.h" +#include "mozilla/a11y/PDocAccessibleParent.h" +#include "mozilla/a11y/ProxyAccessible.h" +#include "nsClassHashtable.h" +#include "nsHashKeys.h" +#include "nsISupportsImpl.h" + +namespace mozilla { +namespace a11y { + +class xpcAccessibleGeneric; + +/* + * These objects live in the main process and comunicate with and represent + * an accessible document in a content process. + */ +class DocAccessibleParent : public ProxyAccessible, + public PDocAccessibleParent +{ +public: + DocAccessibleParent() : + ProxyAccessible(this), mParentDoc(nullptr), + mTopLevel(false), mShutdown(false) + { MOZ_COUNT_CTOR_INHERITED(DocAccessibleParent, ProxyAccessible); } + ~DocAccessibleParent() + { + MOZ_COUNT_DTOR_INHERITED(DocAccessibleParent, ProxyAccessible); + MOZ_ASSERT(mChildDocs.Length() == 0); + MOZ_ASSERT(!ParentDoc()); + } + + void SetTopLevel() { mTopLevel = true; } + bool IsTopLevel() const { return mTopLevel; } + + bool IsShutdown() const { return mShutdown; } + + /* + * Called when a message from a document in a child process notifies the main + * process it is firing an event. + */ + virtual bool RecvEvent(const uint64_t& aID, const uint32_t& aType) + override; + + virtual bool RecvShowEvent(const ShowEventData& aData, const bool& aFromUser) + override; + virtual bool RecvHideEvent(const uint64_t& aRootID, const bool& aFromUser) + override; + virtual bool RecvStateChangeEvent(const uint64_t& aID, + const uint64_t& aState, + const bool& aEnabled) override final; + + virtual bool RecvCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset) + override final; + + virtual bool RecvTextChangeEvent(const uint64_t& aID, const nsString& aStr, + const int32_t& aStart, const uint32_t& aLen, + const bool& aIsInsert, + const bool& aFromUser) override; + + virtual bool RecvSelectionEvent(const uint64_t& aID, + const uint64_t& aWidgetID, + const uint32_t& aType) override; + + virtual bool RecvRoleChangedEvent(const uint32_t& aRole) override final; + + virtual bool RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID) override; + + void Unbind() + { + if (DocAccessibleParent* parent = ParentDoc()) { + parent->RemoveChildDoc(this); + } + + mParent = nullptr; + } + + virtual bool RecvShutdown() override; + void Destroy(); + virtual void ActorDestroy(ActorDestroyReason aWhy) override + { + MOZ_DIAGNOSTIC_ASSERT(CheckDocTree()); + if (!mShutdown) + Destroy(); + } + + /* + * Return the main processes representation of the parent document (if any) + * of the document this object represents. + */ + DocAccessibleParent* ParentDoc() const { return mParentDoc; } + + /* + * Called when a document in a content process notifies the main process of a + * new child document. + */ + bool AddChildDoc(DocAccessibleParent* aChildDoc, uint64_t aParentID, + bool aCreating = true); + + /* + * Called when the document in the content process this object represents + * notifies the main process a child document has been removed. + */ + void RemoveChildDoc(DocAccessibleParent* aChildDoc) + { + aChildDoc->Parent()->ClearChildDoc(aChildDoc); + mChildDocs.RemoveElement(aChildDoc); + aChildDoc->mParentDoc = nullptr; + MOZ_ASSERT(aChildDoc->mChildDocs.Length() == 0); + } + + void RemoveAccessible(ProxyAccessible* aAccessible) + { + MOZ_DIAGNOSTIC_ASSERT(mAccessibles.GetEntry(aAccessible->ID())); + mAccessibles.RemoveEntry(aAccessible->ID()); + } + + /** + * Return the accessible for given id. + */ + ProxyAccessible* GetAccessible(uintptr_t aID) + { + if (!aID) + return this; + + ProxyEntry* e = mAccessibles.GetEntry(aID); + return e ? e->mProxy : nullptr; + } + + const ProxyAccessible* GetAccessible(uintptr_t aID) const + { return const_cast<DocAccessibleParent*>(this)->GetAccessible(aID); } + + size_t ChildDocCount() const { return mChildDocs.Length(); } + const DocAccessibleParent* ChildDocAt(size_t aIdx) const + { return mChildDocs[aIdx]; } + +#if defined(XP_WIN) + void SetCOMProxy(const RefPtr<IAccessible>& aCOMProxy); + + virtual bool RecvGetWindowedPluginIAccessible( + const WindowsHandle& aHwnd, IAccessibleHolder* aPluginCOMProxy) override; +#endif + +private: + + class ProxyEntry : public PLDHashEntryHdr + { + public: + explicit ProxyEntry(const void*) : mProxy(nullptr) {} + ProxyEntry(ProxyEntry&& aOther) : + mProxy(aOther.mProxy) { aOther.mProxy = nullptr; } + ~ProxyEntry() { delete mProxy; } + + typedef uint64_t KeyType; + typedef const void* KeyTypePointer; + + bool KeyEquals(const void* aKey) const + { return mProxy->ID() == (uint64_t)aKey; } + + static const void* KeyToPointer(uint64_t aKey) { return (void*)aKey; } + + static PLDHashNumber HashKey(const void* aKey) { return (uint64_t)aKey; } + + enum { ALLOW_MEMMOVE = true }; + + ProxyAccessible* mProxy; + }; + + uint32_t AddSubtree(ProxyAccessible* aParent, + const nsTArray<AccessibleData>& aNewTree, uint32_t aIdx, + uint32_t aIdxInParent); + MOZ_MUST_USE bool CheckDocTree() const; + xpcAccessibleGeneric* GetXPCAccessible(ProxyAccessible* aProxy); + + nsTArray<DocAccessibleParent*> mChildDocs; + DocAccessibleParent* mParentDoc; + + /* + * Conceptually this is a map from IDs to proxies, but we store the ID in the + * proxy object so we can't use a real map. + */ + nsTHashtable<ProxyEntry> mAccessibles; + bool mTopLevel; + bool mShutdown; +}; + +} +} + +#endif diff --git a/accessible/ipc/IPCTypes.h b/accessible/ipc/IPCTypes.h new file mode 100644 index 0000000000..0e77c6348b --- /dev/null +++ b/accessible/ipc/IPCTypes.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=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/. */ + +#ifndef mozilla_a11y_IPCTypes_h +#define mozilla_a11y_IPCTypes_h + +/** + * Since IPDL does not support preprocessing, this header file allows us to + * define types used by PDocAccessible differently depending on platform. + */ + +#if defined(XP_WIN) && defined(ACCESSIBILITY) + +// So that we don't include a bunch of other Windows junk. +#if !defined(COM_NO_WINDOWS_H) +#define COM_NO_WINDOWS_H +#endif // !defined(COM_NO_WINDOWS_H) + +// COM headers pull in MSXML which conflicts with our own XMLDocument class. +// This define excludes those conflicting definitions. +#if !defined(__XMLDocument_FWD_DEFINED__) +#define __XMLDocument_FWD_DEFINED__ +#endif // !defined(__XMLDocument_FWD_DEFINED__) + +#include "mozilla/a11y/COMPtrTypes.h" + +// This define in rpcndr.h messes up our code, so we must undefine it after +// COMPtrTypes.h has been included. +#if defined(small) +#undef small +#endif // defined(small) + +#else + +namespace mozilla { +namespace a11y { + +typedef uint32_t IAccessibleHolder; + +} // namespace a11y +} // namespace mozilla + +#endif // defined(XP_WIN) && defined(ACCESSIBILITY) + +#endif // mozilla_a11y_IPCTypes_h + 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 diff --git a/accessible/ipc/ProxyAccessibleBase.h b/accessible/ipc/ProxyAccessibleBase.h new file mode 100644 index 0000000000..bea669ffac --- /dev/null +++ b/accessible/ipc/ProxyAccessibleBase.h @@ -0,0 +1,211 @@ +/* -*- 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/. */ + +#ifndef mozilla_a11y_ProxyAccessibleBase_h +#define mozilla_a11y_ProxyAccessibleBase_h + +#include "mozilla/a11y/Role.h" +#include "nsIAccessibleText.h" +#include "nsIAccessibleTypes.h" +#include "Accessible.h" +#include "nsString.h" +#include "nsTArray.h" +#include "nsRect.h" +#include "Accessible.h" + +namespace mozilla { +namespace a11y { + +class Accessible; +class Attribute; +class DocAccessibleParent; +class ProxyAccessible; +enum class RelationType; + +enum Interfaces +{ + HYPERTEXT = 1, + HYPERLINK = 1 << 1, + IMAGE = 1 << 2, + VALUE = 1 << 3, + TABLE = 1 << 4, + TABLECELL = 1 << 5, + DOCUMENT = 1 << 6, + SELECTION = 1 << 7, + ACTION = 1 << 8, +}; + +template <class Derived> +class ProxyAccessibleBase +{ +public: + ~ProxyAccessibleBase() + { + MOZ_ASSERT(!mWrapper); + } + + void AddChildAt(uint32_t aIdx, Derived* aChild) + { mChildren.InsertElementAt(aIdx, aChild); } + + uint32_t ChildrenCount() const { return mChildren.Length(); } + Derived* ChildAt(uint32_t aIdx) const { return mChildren[aIdx]; } + Derived* FirstChild() const + { return mChildren.Length() ? mChildren[0] : nullptr; } + Derived* LastChild() const + { return mChildren.Length() ? mChildren[mChildren.Length() - 1] : nullptr; } + Derived* PrevSibling() const + { + size_t idx = IndexInParent(); + return idx > 0 ? Parent()->mChildren[idx - 1] : nullptr; + } + Derived* NextSibling() const + { + size_t idx = IndexInParent(); + return idx + 1 < Parent()->mChildren.Length() ? Parent()->mChildren[idx + 1] + : nullptr; + } + + // XXX evaluate if this is fast enough. + size_t IndexInParent() const { return + Parent()->mChildren.IndexOf(static_cast<const Derived*>(this)); } + uint32_t EmbeddedChildCount() const; + int32_t IndexOfEmbeddedChild(const Derived* aChild); + Derived* EmbeddedChildAt(size_t aChildIdx); + bool MustPruneChildren() const; + + void Shutdown(); + + void SetChildDoc(DocAccessibleParent* aChildDoc); + void ClearChildDoc(DocAccessibleParent* aChildDoc); + + /** + * Remove The given child. + */ + void RemoveChild(Derived* aChild) + { mChildren.RemoveElement(aChild); } + + /** + * Return the proxy for the parent of the wrapped accessible. + */ + Derived* Parent() const { return mParent; } + + Accessible* OuterDocOfRemoteBrowser() const; + + /** + * Get the role of the accessible we're proxying. + */ + role Role() const { return mRole; } + + /** + * Return true if this is an embedded object. + */ + bool IsEmbeddedObject() const + { + role role = Role(); + return role != roles::TEXT_LEAF && + role != roles::WHITESPACE && + role != roles::STATICTEXT; + } + + /** + * Allow the platform to store a pointers worth of data on us. + */ + uintptr_t GetWrapper() const { return mWrapper; } + void SetWrapper(uintptr_t aWrapper) { mWrapper = aWrapper; } + + /* + * Return the ID of the accessible being proxied. + */ + uint64_t ID() const { return mID; } + + /** + * Return the document containing this proxy, or the proxy itself if it is a + * document. + */ + DocAccessibleParent* Document() const { return mDoc; } + + /** + * Return true if this proxy is a DocAccessibleParent. + */ + bool IsDoc() const { return mIsDoc; } + DocAccessibleParent* AsDoc() const { return IsDoc() ? mDoc : nullptr; } + + // XXX checking mRole alone may not result in same behavior as Accessibles + // due to ARIA roles. See bug 1210477. + inline bool IsTable() const + { + return mRole == roles::TABLE || mRole == roles::MATHML_TABLE; + } + inline bool IsTableRow() const + { + return (mRole == roles::ROW || + mRole == roles::MATHML_TABLE_ROW || + mRole == roles::MATHML_LABELED_ROW); + } + inline bool IsTableCell() const + { + return (mRole == roles::CELL || + mRole == roles::COLUMNHEADER || + mRole == roles::ROWHEADER || + mRole == roles::GRID_CELL || + mRole == roles::MATHML_CELL); + } + +protected: + ProxyAccessibleBase(uint64_t aID, Derived* aParent, + DocAccessibleParent* aDoc, role aRole, + uint32_t aInterfaces) + : mParent(aParent) + , mDoc(aDoc) + , mWrapper(0) + , mID(aID) + , mRole(aRole) + , mOuterDoc(false) + , mIsDoc(false) + , mHasValue(aInterfaces & Interfaces::VALUE) + , mIsHyperLink(aInterfaces & Interfaces::HYPERLINK) + , mIsHyperText(aInterfaces & Interfaces::HYPERTEXT) + { + } + + explicit ProxyAccessibleBase(DocAccessibleParent* aThisAsDoc) : + mParent(nullptr), mDoc(aThisAsDoc), mWrapper(0), mID(0), + mRole(roles::DOCUMENT), mOuterDoc(false), mIsDoc(true), mHasValue(false), + mIsHyperLink(false), mIsHyperText(false) + {} + +protected: + Derived* mParent; + +private: + friend Derived; + + nsTArray<Derived*> mChildren; + DocAccessibleParent* mDoc; + uintptr_t mWrapper; + uint64_t mID; + +protected: + // XXX DocAccessibleParent gets to change this to change the role of + // documents. + role mRole : 27; + +private: + bool mOuterDoc : 1; + +public: + const bool mIsDoc: 1; + const bool mHasValue: 1; + const bool mIsHyperLink: 1; + const bool mIsHyperText: 1; +}; + +extern template class ProxyAccessibleBase<ProxyAccessible>; + +} +} + +#endif diff --git a/accessible/ipc/ProxyAccessibleShared.h b/accessible/ipc/ProxyAccessibleShared.h new file mode 100644 index 0000000000..e940d72ed3 --- /dev/null +++ b/accessible/ipc/ProxyAccessibleShared.h @@ -0,0 +1,277 @@ +/* -*- 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/. */ + +#ifndef mozilla_a11y_ProxyAccessibleShared_h +#define mozilla_a11y_ProxyAccessibleShared_h + +/** + * These are function declarations shared between win/ProxyAccessible.h and + * other/ProxyAccessible.h. + */ + +/* + * Return the states for the proxied accessible. + */ +uint64_t State() const; + +/* + * Return the native states for the proxied accessible. + */ +uint64_t NativeState() const; + +/* + * Set aName to the name of the proxied accessible. + */ +void Name(nsString& aName) const; + +/* + * Set aValue to the value of the proxied accessible. + */ +void Value(nsString& aValue) const; + +/* + * Set aHelp to the help string of the proxied accessible. + */ +void Help(nsString& aHelp) const; + +/** + * Set aDesc to the description of the proxied accessible. + */ +void Description(nsString& aDesc) const; + +/** + * Get the set of attributes on the proxied accessible. + */ +void Attributes(nsTArray<Attribute> *aAttrs) const; + +/** + * Return set of targets of given relation type. + */ +nsTArray<ProxyAccessible*> RelationByType(RelationType aType) const; + +/** + * Get all relations for this accessible. + */ +void Relations(nsTArray<RelationType>* aTypes, + nsTArray<nsTArray<ProxyAccessible*>>* aTargetSets) const; + +bool IsSearchbox() const; + +nsIAtom* LandmarkRole() const; + +nsIAtom* ARIARoleAtom() const; + +int32_t GetLevelInternal(); +void ScrollTo(uint32_t aScrollType); +void ScrollToPoint(uint32_t aScrollType, int32_t aX, int32_t aY); + +int32_t CaretLineNumber(); +int32_t CaretOffset(); +void SetCaretOffset(int32_t aOffset); + +int32_t CharacterCount(); +int32_t SelectionCount(); + +/** + * Get the text between the given offsets. + */ +bool TextSubstring(int32_t aStartOffset, int32_t aEndOfset, + nsString& aText) const; + +void GetTextAfterOffset(int32_t aOffset, AccessibleTextBoundary aBoundaryType, + nsString& aText, int32_t* aStartOffset, + int32_t* aEndOffset); + +void GetTextAtOffset(int32_t aOffset, AccessibleTextBoundary aBoundaryType, + nsString& aText, int32_t* aStartOffset, + int32_t* aEndOffset); + +void GetTextBeforeOffset(int32_t aOffset, AccessibleTextBoundary aBoundaryType, + nsString& aText, int32_t* aStartOffset, + int32_t* aEndOffset); + +char16_t CharAt(int32_t aOffset); + +void TextAttributes(bool aIncludeDefAttrs, + const int32_t aOffset, + nsTArray<Attribute>* aAttributes, + int32_t* aStartOffset, + int32_t* aEndOffset); +void DefaultTextAttributes(nsTArray<Attribute>* aAttrs); + +nsIntRect TextBounds(int32_t aStartOffset, int32_t aEndOffset, + uint32_t aCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE); + +nsIntRect CharBounds(int32_t aOffset, uint32_t aCoordType); + +int32_t OffsetAtPoint(int32_t aX, int32_t aY, uint32_t aCoordType); + +bool SelectionBoundsAt(int32_t aSelectionNum, + nsString& aData, + int32_t* aStartOffset, + int32_t* aEndOffset); + +bool SetSelectionBoundsAt(int32_t aSelectionNum, + int32_t aStartOffset, + int32_t aEndOffset); + +bool AddToSelection(int32_t aStartOffset, + int32_t aEndOffset); + +bool RemoveFromSelection(int32_t aSelectionNum); + +void ScrollSubstringTo(int32_t aStartOffset, int32_t aEndOffset, + uint32_t aScrollType); + +void ScrollSubstringToPoint(int32_t aStartOffset, + int32_t aEndOffset, + uint32_t aCoordinateType, + int32_t aX, int32_t aY); + +void Text(nsString* aText); + +void ReplaceText(const nsString& aText); + +bool InsertText(const nsString& aText, int32_t aPosition); + +bool CopyText(int32_t aStartPos, int32_t aEndPos); + +bool CutText(int32_t aStartPos, int32_t aEndPos); + +bool DeleteText(int32_t aStartPos, int32_t aEndPos); + +bool PasteText(int32_t aPosition); + +nsIntPoint ImagePosition(uint32_t aCoordType); + +nsIntSize ImageSize(); + +uint32_t StartOffset(bool* aOk); + +uint32_t EndOffset(bool* aOk); + +bool IsLinkValid(); + +uint32_t AnchorCount(bool* aOk); + +void AnchorURIAt(uint32_t aIndex, nsCString& aURI, bool* aOk); + +ProxyAccessible* AnchorAt(uint32_t aIndex); + +uint32_t LinkCount(); + +ProxyAccessible* LinkAt(const uint32_t& aIndex); + +int32_t LinkIndexOf(ProxyAccessible* aLink); + +int32_t LinkIndexAtOffset(uint32_t aOffset); + +ProxyAccessible* TableOfACell(); + +uint32_t ColIdx(); + +uint32_t RowIdx(); + +void GetPosition(uint32_t* aColIdx, uint32_t* aRowIdx); + +uint32_t ColExtent(); + +uint32_t RowExtent(); + +void GetColRowExtents(uint32_t* aColIdx, uint32_t* aRowIdx, + uint32_t* aColExtent, uint32_t* aRowExtent); + +void ColHeaderCells(nsTArray<ProxyAccessible*>* aCells); + +void RowHeaderCells(nsTArray<ProxyAccessible*>* aCells); + +bool IsCellSelected(); + +ProxyAccessible* TableCaption(); +void TableSummary(nsString& aSummary); +uint32_t TableColumnCount(); +uint32_t TableRowCount(); +ProxyAccessible* TableCellAt(uint32_t aRow, uint32_t aCol); +int32_t TableCellIndexAt(uint32_t aRow, uint32_t aCol); +int32_t TableColumnIndexAt(uint32_t aCellIndex); +int32_t TableRowIndexAt(uint32_t aCellIndex); +void TableRowAndColumnIndicesAt(uint32_t aCellIndex, + int32_t* aRow, int32_t* aCol); +uint32_t TableColumnExtentAt(uint32_t aRow, uint32_t aCol); +uint32_t TableRowExtentAt(uint32_t aRow, uint32_t aCol); +void TableColumnDescription(uint32_t aCol, nsString& aDescription); +void TableRowDescription(uint32_t aRow, nsString& aDescription); +bool TableColumnSelected(uint32_t aCol); +bool TableRowSelected(uint32_t aRow); +bool TableCellSelected(uint32_t aRow, uint32_t aCol); +uint32_t TableSelectedCellCount(); +uint32_t TableSelectedColumnCount(); +uint32_t TableSelectedRowCount(); +void TableSelectedCells(nsTArray<ProxyAccessible*>* aCellIDs); +void TableSelectedCellIndices(nsTArray<uint32_t>* aCellIndices); +void TableSelectedColumnIndices(nsTArray<uint32_t>* aColumnIndices); +void TableSelectedRowIndices(nsTArray<uint32_t>* aRowIndices); +void TableSelectColumn(uint32_t aCol); +void TableSelectRow(uint32_t aRow); +void TableUnselectColumn(uint32_t aCol); +void TableUnselectRow(uint32_t aRow); +bool TableIsProbablyForLayout(); +ProxyAccessible* AtkTableColumnHeader(int32_t aCol); +ProxyAccessible* AtkTableRowHeader(int32_t aRow); + +void SelectedItems(nsTArray<ProxyAccessible*>* aSelectedItems); +uint32_t SelectedItemCount(); +ProxyAccessible* GetSelectedItem(uint32_t aIndex); +bool IsItemSelected(uint32_t aIndex); +bool AddItemToSelection(uint32_t aIndex); +bool RemoveItemFromSelection(uint32_t aIndex); +bool SelectAll(); +bool UnselectAll(); + +void TakeSelection(); +void SetSelected(bool aSelect); + +bool DoAction(uint8_t aIndex); +uint8_t ActionCount(); +void ActionDescriptionAt(uint8_t aIndex, nsString& aDescription); +void ActionNameAt(uint8_t aIndex, nsString& aName); +KeyBinding AccessKey(); +KeyBinding KeyboardShortcut(); +void AtkKeyBinding(nsString& aBinding); + +double CurValue(); +bool SetCurValue(double aValue); +double MinValue(); +double MaxValue(); +double Step(); + +void TakeFocus(); +ProxyAccessible* FocusedChild(); +ProxyAccessible* ChildAtPoint(int32_t aX, int32_t aY, + Accessible::EWhichChildAtPoint aWhichChild); +nsIntRect Bounds(); + +void Language(nsString& aLocale); +void DocType(nsString& aType); +void Title(nsString& aTitle); +void URL(nsString& aURL); +void MimeType(nsString aMime); +void URLDocTypeMimeType(nsString& aURL, nsString& aDocType, + nsString& aMimeType); + +ProxyAccessible* AccessibleAtPoint(int32_t aX, int32_t aY, + bool aNeedsScreenCoords); + +void Extents(bool aNeedsScreenCoords, int32_t* aX, int32_t* aY, + int32_t* aWidth, int32_t* aHeight); + +/** + * Return the id of the dom node this accessible represents. Note this + * should probably only be used for testing. + */ +void DOMNodeID(nsString& aID); + +#endif diff --git a/accessible/ipc/moz.build b/accessible/ipc/moz.build new file mode 100644 index 0000000000..bb0632cd23 --- /dev/null +++ b/accessible/ipc/moz.build @@ -0,0 +1,61 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +if CONFIG['OS_ARCH'] == 'WINNT': + DIRS += ['win'] + LOCAL_INCLUDES += [ + '/accessible/ipc/win', + '/accessible/windows/ia2', + '/accessible/windows/msaa', + ] +else: + DIRS += ['other'] + LOCAL_INCLUDES += [ + '/accessible/ipc/other', + ] + if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: + LOCAL_INCLUDES += [ + '/accessible/atk', + ] + elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': + LOCAL_INCLUDES += [ + '/accessible/mac', + ] + else: + LOCAL_INCLUDES += [ + '/accessible/other', + ] + +EXPORTS.mozilla.a11y += [ + 'IPCTypes.h', +] + +if CONFIG['GNU_CXX']: + CXXFLAGS += ['-Wno-error=shadow'] + +if CONFIG['ACCESSIBILITY']: + EXPORTS.mozilla.a11y += [ + 'DocAccessibleChildBase.h', + 'DocAccessibleParent.h', + 'ProxyAccessibleBase.h', + 'ProxyAccessibleShared.h', + ] + + UNIFIED_SOURCES += [ + 'DocAccessibleChildBase.cpp', + 'DocAccessibleParent.cpp', + 'ProxyAccessibleBase.cpp', + ] + + LOCAL_INCLUDES += [ + '/accessible/base', + '/accessible/generic', + '/accessible/xpcom', + ] + +include('/ipc/chromium/chromium-config.mozbuild') + +FINAL_LIBRARY = 'xul' diff --git a/accessible/ipc/other/DocAccessibleChild.cpp b/accessible/ipc/other/DocAccessibleChild.cpp new file mode 100644 index 0000000000..045b789394 --- /dev/null +++ b/accessible/ipc/other/DocAccessibleChild.cpp @@ -0,0 +1,1998 @@ +/* -*- 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 "DocAccessibleChild.h" + +#include "Accessible-inl.h" +#include "ProxyAccessible.h" +#include "Relation.h" +#include "HyperTextAccessible-inl.h" +#include "TextLeafAccessible.h" +#include "ImageAccessible.h" +#include "TableAccessible.h" +#include "TableCellAccessible.h" +#include "nsIPersistentProperties2.h" +#include "nsISimpleEnumerator.h" +#include "nsAccUtils.h" +#ifdef MOZ_ACCESSIBILITY_ATK +#include "AccessibleWrap.h" +#endif + +namespace mozilla { +namespace a11y { + +Accessible* +DocAccessibleChild::IdToAccessible(const uint64_t& aID) const +{ + if (!aID) + return mDoc; + + if (!mDoc) + return nullptr; + + return mDoc->GetAccessibleByUniqueID(reinterpret_cast<void*>(aID)); +} + +Accessible* +DocAccessibleChild::IdToAccessibleLink(const uint64_t& aID) const +{ + Accessible* acc = IdToAccessible(aID); + return acc && acc->IsLink() ? acc : nullptr; +} + +Accessible* +DocAccessibleChild::IdToAccessibleSelect(const uint64_t& aID) const +{ + Accessible* acc = IdToAccessible(aID); + return acc && acc->IsSelect() ? acc : nullptr; +} + +HyperTextAccessible* +DocAccessibleChild::IdToHyperTextAccessible(const uint64_t& aID) const +{ + Accessible* acc = IdToAccessible(aID); + return acc && acc->IsHyperText() ? acc->AsHyperText() : nullptr; +} + +TextLeafAccessible* +DocAccessibleChild::IdToTextLeafAccessible(const uint64_t& aID) const +{ + Accessible* acc = IdToAccessible(aID); + return acc && acc->IsTextLeaf() ? acc->AsTextLeaf() : nullptr; +} + +ImageAccessible* +DocAccessibleChild::IdToImageAccessible(const uint64_t& aID) const +{ + Accessible* acc = IdToAccessible(aID); + return (acc && acc->IsImage()) ? acc->AsImage() : nullptr; +} + +TableCellAccessible* +DocAccessibleChild::IdToTableCellAccessible(const uint64_t& aID) const +{ + Accessible* acc = IdToAccessible(aID); + return (acc && acc->IsTableCell()) ? acc->AsTableCell() : nullptr; +} + +TableAccessible* +DocAccessibleChild::IdToTableAccessible(const uint64_t& aID) const +{ + Accessible* acc = IdToAccessible(aID); + return (acc && acc->IsTable()) ? acc->AsTable() : nullptr; +} + +bool +DocAccessibleChild::RecvState(const uint64_t& aID, uint64_t* aState) +{ + Accessible* acc = IdToAccessible(aID); + if (!acc) { + *aState = states::DEFUNCT; + return true; + } + + *aState = acc->State(); + + return true; +} + +bool +DocAccessibleChild::RecvNativeState(const uint64_t& aID, uint64_t* aState) +{ + Accessible* acc = IdToAccessible(aID); + if (!acc) { + *aState = states::DEFUNCT; + return true; + } + + *aState = acc->NativeState(); + + return true; +} + +bool +DocAccessibleChild::RecvName(const uint64_t& aID, nsString* aName) +{ + Accessible* acc = IdToAccessible(aID); + if (!acc) + return true; + + acc->Name(*aName); + return true; +} + +bool +DocAccessibleChild::RecvValue(const uint64_t& aID, nsString* aValue) +{ + Accessible* acc = IdToAccessible(aID); + if (!acc) { + return true; + } + + acc->Value(*aValue); + return true; +} + +bool +DocAccessibleChild::RecvHelp(const uint64_t& aID, nsString* aHelp) +{ + Accessible* acc = IdToAccessible(aID); + if (!acc) { + return true; + } + + acc->Help(*aHelp); + return true; +} + +bool +DocAccessibleChild::RecvDescription(const uint64_t& aID, nsString* aDesc) +{ + Accessible* acc = IdToAccessible(aID); + if (!acc) + return true; + + acc->Description(*aDesc); + return true; +} + +bool +DocAccessibleChild::RecvAttributes(const uint64_t& aID, nsTArray<Attribute>* aAttributes) +{ + Accessible* acc = IdToAccessible(aID); + if (!acc) + return true; + + nsCOMPtr<nsIPersistentProperties> props = acc->Attributes(); + return PersistentPropertiesToArray(props, aAttributes); +} + +bool +DocAccessibleChild::PersistentPropertiesToArray(nsIPersistentProperties* aProps, + nsTArray<Attribute>* aAttributes) +{ + if (!aProps) { + return true; + } + nsCOMPtr<nsISimpleEnumerator> propEnum; + nsresult rv = aProps->Enumerate(getter_AddRefs(propEnum)); + NS_ENSURE_SUCCESS(rv, false); + + bool hasMore; + while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) { + nsCOMPtr<nsISupports> sup; + rv = propEnum->GetNext(getter_AddRefs(sup)); + NS_ENSURE_SUCCESS(rv, false); + + nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(sup)); + NS_ENSURE_TRUE(propElem, false); + + nsAutoCString name; + rv = propElem->GetKey(name); + NS_ENSURE_SUCCESS(rv, false); + + nsAutoString value; + rv = propElem->GetValue(value); + NS_ENSURE_SUCCESS(rv, false); + + aAttributes->AppendElement(Attribute(name, value)); + } + + return true; +} + +bool +DocAccessibleChild::RecvRelationByType(const uint64_t& aID, + const uint32_t& aType, + nsTArray<uint64_t>* aTargets) +{ + Accessible* acc = IdToAccessible(aID); + if (!acc) + return true; + + auto type = static_cast<RelationType>(aType); + Relation rel = acc->RelationByType(type); + while (Accessible* target = rel.Next()) + aTargets->AppendElement(reinterpret_cast<uintptr_t>(target)); + + return true; +} + +static void +AddRelation(Accessible* aAcc, RelationType aType, + nsTArray<RelationTargets>* aTargets) +{ + Relation rel = aAcc->RelationByType(aType); + nsTArray<uint64_t> targets; + while (Accessible* target = rel.Next()) + targets.AppendElement(reinterpret_cast<uintptr_t>(target)); + + if (!targets.IsEmpty()) { + RelationTargets* newRelation = + aTargets->AppendElement(RelationTargets(static_cast<uint32_t>(aType), + nsTArray<uint64_t>())); + newRelation->Targets().SwapElements(targets); + } +} + +bool +DocAccessibleChild::RecvRelations(const uint64_t& aID, + nsTArray<RelationTargets>* aRelations) +{ + Accessible* acc = IdToAccessible(aID); + if (!acc) + return true; + +#define RELATIONTYPE(gecko, s, a, m, i) AddRelation(acc, RelationType::gecko, aRelations); + +#include "RelationTypeMap.h" +#undef RELATIONTYPE + + return true; +} + +bool +DocAccessibleChild::RecvIsSearchbox(const uint64_t& aID, bool* aRetVal) +{ + Accessible* acc = IdToAccessible(aID); + if (!acc) + return true; + + *aRetVal = acc->IsSearchbox(); + return true; +} + +bool +DocAccessibleChild::RecvLandmarkRole(const uint64_t& aID, nsString* aLandmark) +{ + Accessible* acc = IdToAccessible(aID); + if (!acc) { + return true; + } + + if (nsIAtom* roleAtom = acc->LandmarkRole()) { + roleAtom->ToString(*aLandmark); + } + + return true; +} + +bool +DocAccessibleChild::RecvARIARoleAtom(const uint64_t& aID, nsString* aRole) +{ + Accessible* acc = IdToAccessible(aID); + if (!acc) { + return true; + } + + if (const nsRoleMapEntry* roleMap = acc->ARIARoleMap()) { + if (nsIAtom* roleAtom = *(roleMap->roleAtom)) { + roleAtom->ToString(*aRole); + } + } + + return true; +} + +bool +DocAccessibleChild::RecvGetLevelInternal(const uint64_t& aID, int32_t* aLevel) +{ + Accessible* acc = IdToAccessible(aID); + if (acc) { + *aLevel = acc->GetLevelInternal(); + } + return true; +} + +bool +DocAccessibleChild::RecvScrollTo(const uint64_t& aID, + const uint32_t& aScrollType) +{ + Accessible* acc = IdToAccessible(aID); + if (acc) { + nsCoreUtils::ScrollTo(acc->Document()->PresShell(), acc->GetContent(), + aScrollType); + } + + return true; +} + +bool +DocAccessibleChild::RecvScrollToPoint(const uint64_t& aID, const uint32_t& aScrollType, const int32_t& aX, const int32_t& aY) +{ + Accessible* acc = IdToAccessible(aID); + if (acc) { + acc->ScrollToPoint(aScrollType, aX, aY); + } + + return true; +} + +bool +DocAccessibleChild::RecvCaretLineNumber(const uint64_t& aID, int32_t* aLineNumber) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + *aLineNumber = acc && acc->IsTextRole() ? acc->CaretLineNumber() : 0; + return true; +} + +bool +DocAccessibleChild::RecvCaretOffset(const uint64_t& aID, int32_t* aOffset) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + *aOffset = acc && acc->IsTextRole() ? acc->CaretOffset() : 0; + return true; +} + +bool +DocAccessibleChild::RecvSetCaretOffset(const uint64_t& aID, + const int32_t& aOffset) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc && acc->IsTextRole() && acc->IsValidOffset(aOffset)) { + acc->SetCaretOffset(aOffset); + } + return true; +} + +bool +DocAccessibleChild::RecvCharacterCount(const uint64_t& aID, int32_t* aCount) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + *aCount = acc ? acc->CharacterCount() : 0; + return true; +} + +bool +DocAccessibleChild::RecvSelectionCount(const uint64_t& aID, int32_t* aCount) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + *aCount = acc ? acc->SelectionCount() : 0; + return true; +} + +bool +DocAccessibleChild::RecvTextSubstring(const uint64_t& aID, + const int32_t& aStartOffset, + const int32_t& aEndOffset, + nsString* aText, bool* aValid) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (!acc) { + return true; + } + + *aValid = acc->IsValidRange(aStartOffset, aEndOffset); + acc->TextSubstring(aStartOffset, aEndOffset, *aText); + return true; +} + +bool +DocAccessibleChild::RecvGetTextAfterOffset(const uint64_t& aID, + const int32_t& aOffset, + const int32_t& aBoundaryType, + nsString* aText, + int32_t* aStartOffset, + int32_t* aEndOffset) +{ + *aStartOffset = 0; + *aEndOffset = 0; + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc) { + acc->TextAfterOffset(aOffset, aBoundaryType, + aStartOffset, aEndOffset, *aText); + } + return true; +} + +bool +DocAccessibleChild::RecvGetTextAtOffset(const uint64_t& aID, + const int32_t& aOffset, + const int32_t& aBoundaryType, + nsString* aText, + int32_t* aStartOffset, + int32_t* aEndOffset) +{ + *aStartOffset = 0; + *aEndOffset = 0; + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc) { + acc->TextAtOffset(aOffset, aBoundaryType, + aStartOffset, aEndOffset, *aText); + } + return true; +} + +bool +DocAccessibleChild::RecvGetTextBeforeOffset(const uint64_t& aID, + const int32_t& aOffset, + const int32_t& aBoundaryType, + nsString* aText, + int32_t* aStartOffset, + int32_t* aEndOffset) +{ + *aStartOffset = 0; + *aEndOffset = 0; + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc) { + acc->TextBeforeOffset(aOffset, aBoundaryType, + aStartOffset, aEndOffset, *aText); + } + return true; +} + +bool +DocAccessibleChild::RecvCharAt(const uint64_t& aID, + const int32_t& aOffset, + uint16_t* aChar) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + *aChar = acc && acc->IsTextRole() ? + static_cast<uint16_t>(acc->CharAt(aOffset)) : 0; + return true; +} + +bool +DocAccessibleChild::RecvTextAttributes(const uint64_t& aID, + const bool& aIncludeDefAttrs, + const int32_t& aOffset, + nsTArray<Attribute>* aAttributes, + int32_t* aStartOffset, + int32_t* aEndOffset) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (!acc || !acc->IsTextRole()) { + return true; + } + + nsCOMPtr<nsIPersistentProperties> props = + acc->TextAttributes(aIncludeDefAttrs, aOffset, aStartOffset, aEndOffset); + return PersistentPropertiesToArray(props, aAttributes); +} + +bool +DocAccessibleChild::RecvDefaultTextAttributes(const uint64_t& aID, + nsTArray<Attribute> *aAttributes) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (!acc || !acc->IsTextRole()) { + return true; + } + + nsCOMPtr<nsIPersistentProperties> props = acc->DefaultTextAttributes(); + return PersistentPropertiesToArray(props, aAttributes); +} + +bool +DocAccessibleChild::RecvTextBounds(const uint64_t& aID, + const int32_t& aStartOffset, + const int32_t& aEndOffset, + const uint32_t& aCoordType, + nsIntRect* aRetVal) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc && acc->IsTextRole()) { + *aRetVal = acc->TextBounds(aStartOffset, aEndOffset, aCoordType); + } + + return true; +} + +bool +DocAccessibleChild::RecvCharBounds(const uint64_t& aID, + const int32_t& aOffset, + const uint32_t& aCoordType, + nsIntRect* aRetVal) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc && acc->IsTextRole()) { + *aRetVal = acc->CharBounds(aOffset, aCoordType); + } + + return true; +} + +bool +DocAccessibleChild::RecvOffsetAtPoint(const uint64_t& aID, + const int32_t& aX, + const int32_t& aY, + const uint32_t& aCoordType, + int32_t* aRetVal) +{ + *aRetVal = -1; + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc && acc->IsTextRole()) { + *aRetVal = acc->OffsetAtPoint(aX, aY, aCoordType); + } + return true; +} + +bool +DocAccessibleChild::RecvSelectionBoundsAt(const uint64_t& aID, + const int32_t& aSelectionNum, + bool* aSucceeded, + nsString* aData, + int32_t* aStartOffset, + int32_t* aEndOffset) +{ + *aSucceeded = false; + *aStartOffset = 0; + *aEndOffset = 0; + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc && acc->IsTextRole()) { + *aSucceeded = + acc->SelectionBoundsAt(aSelectionNum, aStartOffset, aEndOffset); + if (*aSucceeded) { + acc->TextSubstring(*aStartOffset, *aEndOffset, *aData); + } + } + + return true; +} + +bool +DocAccessibleChild::RecvSetSelectionBoundsAt(const uint64_t& aID, + const int32_t& aSelectionNum, + const int32_t& aStartOffset, + const int32_t& aEndOffset, + bool* aSucceeded) +{ + *aSucceeded = false; + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc && acc->IsTextRole()) { + *aSucceeded = + acc->SetSelectionBoundsAt(aSelectionNum, aStartOffset, aEndOffset); + } + + return true; +} + +bool +DocAccessibleChild::RecvAddToSelection(const uint64_t& aID, + const int32_t& aStartOffset, + const int32_t& aEndOffset, + bool* aSucceeded) +{ + *aSucceeded = false; + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc && acc->IsTextRole()) { + *aSucceeded = acc->AddToSelection(aStartOffset, aEndOffset); + } + + return true; +} + +bool +DocAccessibleChild::RecvRemoveFromSelection(const uint64_t& aID, + const int32_t& aSelectionNum, + bool* aSucceeded) +{ + *aSucceeded = false; + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc && acc->IsTextRole()) { + *aSucceeded = acc->RemoveFromSelection(aSelectionNum); + } + + return true; +} + +bool +DocAccessibleChild::RecvScrollSubstringTo(const uint64_t& aID, + const int32_t& aStartOffset, + const int32_t& aEndOffset, + const uint32_t& aScrollType) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc) { + acc->ScrollSubstringTo(aStartOffset, aEndOffset, aScrollType); + } + + return true; +} + +bool +DocAccessibleChild::RecvScrollSubstringToPoint(const uint64_t& aID, + const int32_t& aStartOffset, + const int32_t& aEndOffset, + const uint32_t& aCoordinateType, + const int32_t& aX, + const int32_t& aY) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc) { + acc->ScrollSubstringToPoint(aStartOffset, aEndOffset, aCoordinateType, + aX, aY); + } + + return true; +} + +bool +DocAccessibleChild::RecvText(const uint64_t& aID, + nsString* aText) +{ + TextLeafAccessible* acc = IdToTextLeafAccessible(aID); + if (acc) { + *aText = acc->Text(); + } + + return true; +} + +bool +DocAccessibleChild::RecvReplaceText(const uint64_t& aID, + const nsString& aText) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc && acc->IsTextRole()) { + acc->ReplaceText(aText); + } + + return true; +} + +bool +DocAccessibleChild::RecvInsertText(const uint64_t& aID, + const nsString& aText, + const int32_t& aPosition, bool* aValid) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc && acc->IsTextRole()) { + *aValid = acc->IsValidOffset(aPosition); + acc->InsertText(aText, aPosition); + } + + return true; +} + +bool +DocAccessibleChild::RecvCopyText(const uint64_t& aID, + const int32_t& aStartPos, + const int32_t& aEndPos, bool* aValid) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc && acc->IsTextRole()) { + acc->CopyText(aStartPos, aEndPos); + } + + return true; +} + +bool +DocAccessibleChild::RecvCutText(const uint64_t& aID, + const int32_t& aStartPos, + const int32_t& aEndPos, bool* aValid) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc && acc->IsTextRole()) { + *aValid = acc->IsValidRange(aStartPos, aEndPos); + acc->CutText(aStartPos, aEndPos); + } + + return true; +} + +bool +DocAccessibleChild::RecvDeleteText(const uint64_t& aID, + const int32_t& aStartPos, + const int32_t& aEndPos, bool* aValid) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc && acc->IsTextRole()) { + *aValid = acc->IsValidRange(aStartPos, aEndPos); + acc->DeleteText(aStartPos, aEndPos); + } + + return true; +} + +bool +DocAccessibleChild::RecvPasteText(const uint64_t& aID, + const int32_t& aPosition, bool* aValid) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc && acc->IsTextRole()) { + *aValid = acc->IsValidOffset(aPosition); + acc->PasteText(aPosition); + } + + return true; +} + +bool +DocAccessibleChild::RecvImagePosition(const uint64_t& aID, + const uint32_t& aCoordType, + nsIntPoint* aRetVal) +{ + ImageAccessible* acc = IdToImageAccessible(aID); + if (acc) { + *aRetVal = acc->Position(aCoordType); + } + + return true; +} + +bool +DocAccessibleChild::RecvImageSize(const uint64_t& aID, + nsIntSize* aRetVal) +{ + + ImageAccessible* acc = IdToImageAccessible(aID); + if (acc) { + *aRetVal = acc->Size(); + } + + return true; +} + +bool +DocAccessibleChild::RecvStartOffset(const uint64_t& aID, + uint32_t* aRetVal, + bool* aOk) +{ + Accessible* acc = IdToAccessibleLink(aID); + if (acc) { + *aRetVal = acc->StartOffset(); + *aOk = true; + } else { + *aRetVal = 0; + *aOk = false; + } + + return true; +} + +bool +DocAccessibleChild::RecvEndOffset(const uint64_t& aID, + uint32_t* aRetVal, + bool* aOk) +{ + Accessible* acc = IdToAccessibleLink(aID); + if (acc) { + *aRetVal = acc->EndOffset(); + *aOk = true; + } else { + *aRetVal = 0; + *aOk = false; + } + + return true; +} + +bool +DocAccessibleChild::RecvIsLinkValid(const uint64_t& aID, + bool* aRetVal) +{ + Accessible* acc = IdToAccessibleLink(aID); + if (acc) { + *aRetVal = acc->IsLinkValid(); + } else { + *aRetVal = false; + } + + return true; +} + +bool +DocAccessibleChild::RecvAnchorCount(const uint64_t& aID, + uint32_t* aRetVal, + bool* aOk) +{ + Accessible* acc = IdToAccessibleLink(aID); + if (acc) { + *aRetVal = acc->AnchorCount(); + *aOk = true; + } else { + *aRetVal = 0; + *aOk = false; + } + + return true; +} + +bool +DocAccessibleChild::RecvAnchorURIAt(const uint64_t& aID, + const uint32_t& aIndex, + nsCString* aURI, + bool* aOk) +{ + Accessible* acc = IdToAccessibleLink(aID); + *aOk = false; + if (acc) { + nsCOMPtr<nsIURI> uri = acc->AnchorURIAt(aIndex); + if (uri) { + uri->GetSpec(*aURI); + *aOk = true; + } + } + + return true; +} + +bool +DocAccessibleChild::RecvAnchorAt(const uint64_t& aID, + const uint32_t& aIndex, + uint64_t* aIDOfAnchor, + bool* aOk) +{ + *aIDOfAnchor = 0; + *aOk = false; + Accessible* acc = IdToAccessibleLink(aID); + if (acc) { + Accessible* anchor = acc->AnchorAt(aIndex); + if (anchor) { + *aIDOfAnchor = reinterpret_cast<uint64_t>(anchor->UniqueID()); + *aOk = true; + } + } + + return true; +} + +bool +DocAccessibleChild::RecvLinkCount(const uint64_t& aID, + uint32_t* aCount) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + *aCount = acc ? acc->LinkCount() : 0; + return true; +} + +bool +DocAccessibleChild::RecvLinkAt(const uint64_t& aID, + const uint32_t& aIndex, + uint64_t* aIDOfLink, + bool* aOk) +{ + *aIDOfLink = 0; + *aOk = false; + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + if (acc) { + Accessible* link = acc->LinkAt(aIndex); + if (link) { + *aIDOfLink = reinterpret_cast<uint64_t>(link->UniqueID()); + *aOk = true; + } + } + + return true; +} + +bool +DocAccessibleChild::RecvLinkIndexOf(const uint64_t& aID, + const uint64_t& aLinkID, + int32_t* aIndex) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + Accessible* link = IdToAccessible(aLinkID); + *aIndex = -1; + if (acc && link) { + *aIndex = acc->LinkIndexOf(link); + } + + return true; +} + +bool +DocAccessibleChild::RecvLinkIndexAtOffset(const uint64_t& aID, + const uint32_t& aOffset, + int32_t* aIndex) +{ + HyperTextAccessible* acc = IdToHyperTextAccessible(aID); + *aIndex = acc ? acc->LinkIndexAtOffset(aOffset) : -1; + return true; +} + +bool +DocAccessibleChild::RecvTableOfACell(const uint64_t& aID, + uint64_t* aTableID, + bool* aOk) +{ + *aTableID = 0; + *aOk = false; + TableCellAccessible* acc = IdToTableCellAccessible(aID); + if (acc) { + TableAccessible* table = acc->Table(); + if (table) { + *aTableID = reinterpret_cast<uint64_t>(table->AsAccessible()->UniqueID()); + *aOk = true; + } + } + + return true; +} + +bool +DocAccessibleChild::RecvColIdx(const uint64_t& aID, + uint32_t* aIndex) +{ + *aIndex = 0; + TableCellAccessible* acc = IdToTableCellAccessible(aID); + if (acc) { + *aIndex = acc->ColIdx(); + } + + return true; +} + +bool +DocAccessibleChild::RecvRowIdx(const uint64_t& aID, + uint32_t* aIndex) +{ + *aIndex = 0; + TableCellAccessible* acc = IdToTableCellAccessible(aID); + if (acc) { + *aIndex = acc->RowIdx(); + } + + return true; +} + +bool +DocAccessibleChild::RecvGetPosition(const uint64_t& aID, + uint32_t* aColIdx, uint32_t* aRowIdx) +{ + *aColIdx = 0; + *aRowIdx = 0; + TableCellAccessible* acc = IdToTableCellAccessible(aID); + if (acc) { + *aColIdx = acc->ColIdx(); + *aRowIdx = acc->RowIdx(); + } + + return true; +} + +bool +DocAccessibleChild::RecvGetColRowExtents(const uint64_t& aID, + uint32_t* aColIdx, uint32_t* aRowIdx, + uint32_t* aColExtent, uint32_t* aRowExtent) +{ + *aColIdx = 0; + *aRowIdx = 0; + *aColExtent = 0; + *aRowExtent = 0; + TableCellAccessible* acc = IdToTableCellAccessible(aID); + if (acc) { + *aColIdx = acc->ColIdx(); + *aRowIdx = acc->RowIdx(); + *aColExtent = acc->ColExtent(); + *aRowExtent = acc->RowExtent(); + } + + return true; +} + +bool +DocAccessibleChild::RecvColExtent(const uint64_t& aID, + uint32_t* aExtent) +{ + *aExtent = 0; + TableCellAccessible* acc = IdToTableCellAccessible(aID); + if (acc) { + *aExtent = acc->ColExtent(); + } + + return true; +} + +bool +DocAccessibleChild::RecvRowExtent(const uint64_t& aID, + uint32_t* aExtent) +{ + *aExtent = 0; + TableCellAccessible* acc = IdToTableCellAccessible(aID); + if (acc) { + *aExtent = acc->RowExtent(); + } + + return true; +} + +bool +DocAccessibleChild::RecvColHeaderCells(const uint64_t& aID, + nsTArray<uint64_t>* aCells) +{ + TableCellAccessible* acc = IdToTableCellAccessible(aID); + if (acc) { + AutoTArray<Accessible*, 10> headerCells; + acc->ColHeaderCells(&headerCells); + aCells->SetCapacity(headerCells.Length()); + for (uint32_t i = 0; i < headerCells.Length(); ++i) { + aCells->AppendElement( + reinterpret_cast<uint64_t>(headerCells[i]->UniqueID())); + } + } + + return true; +} + +bool +DocAccessibleChild::RecvRowHeaderCells(const uint64_t& aID, + nsTArray<uint64_t>* aCells) +{ + TableCellAccessible* acc = IdToTableCellAccessible(aID); + if (acc) { + AutoTArray<Accessible*, 10> headerCells; + acc->RowHeaderCells(&headerCells); + aCells->SetCapacity(headerCells.Length()); + for (uint32_t i = 0; i < headerCells.Length(); ++i) { + aCells->AppendElement( + reinterpret_cast<uint64_t>(headerCells[i]->UniqueID())); + } + } + + return true; +} + +bool +DocAccessibleChild::RecvIsCellSelected(const uint64_t& aID, + bool* aSelected) +{ + TableCellAccessible* acc = IdToTableCellAccessible(aID); + *aSelected = acc && acc->Selected(); + return true; +} + +bool +DocAccessibleChild::RecvTableCaption(const uint64_t& aID, + uint64_t* aCaptionID, + bool* aOk) +{ + *aCaptionID = 0; + *aOk = false; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + Accessible* caption = acc->Caption(); + if (caption) { + *aCaptionID = reinterpret_cast<uint64_t>(caption->UniqueID()); + *aOk = true; + } + } + + return true; +} + +bool +DocAccessibleChild::RecvTableSummary(const uint64_t& aID, + nsString* aSummary) +{ + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + acc->Summary(*aSummary); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableColumnCount(const uint64_t& aID, + uint32_t* aColCount) +{ + *aColCount = 0; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + *aColCount = acc->ColCount(); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableRowCount(const uint64_t& aID, + uint32_t* aRowCount) +{ + *aRowCount = 0; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + *aRowCount = acc->RowCount(); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableCellAt(const uint64_t& aID, + const uint32_t& aRow, + const uint32_t& aCol, + uint64_t* aCellID, + bool* aOk) +{ + *aCellID = 0; + *aOk = false; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + Accessible* cell = acc->CellAt(aRow, aCol); + if (cell) { + *aCellID = reinterpret_cast<uint64_t>(cell->UniqueID()); + *aOk = true; + } + } + + return true; +} + +bool +DocAccessibleChild::RecvTableCellIndexAt(const uint64_t& aID, + const uint32_t& aRow, + const uint32_t& aCol, + int32_t* aIndex) +{ + *aIndex = -1; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + *aIndex = acc->CellIndexAt(aRow, aCol); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableColumnIndexAt(const uint64_t& aID, + const uint32_t& aCellIndex, + int32_t* aCol) +{ + *aCol = -1; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + *aCol = acc->ColIndexAt(aCellIndex); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableRowIndexAt(const uint64_t& aID, + const uint32_t& aCellIndex, + int32_t* aRow) +{ + *aRow = -1; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + *aRow = acc->RowIndexAt(aCellIndex); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableRowAndColumnIndicesAt(const uint64_t& aID, + const uint32_t& aCellIndex, + int32_t* aRow, + int32_t* aCol) +{ + *aRow = -1; + *aCol = -1; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + acc->RowAndColIndicesAt(aCellIndex, aRow, aCol); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableColumnExtentAt(const uint64_t& aID, + const uint32_t& aRow, + const uint32_t& aCol, + uint32_t* aExtent) +{ + *aExtent = 0; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + *aExtent = acc->ColExtentAt(aRow, aCol); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableRowExtentAt(const uint64_t& aID, + const uint32_t& aRow, + const uint32_t& aCol, + uint32_t* aExtent) +{ + *aExtent = 0; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + *aExtent = acc->RowExtentAt(aRow, aCol); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableColumnDescription(const uint64_t& aID, + const uint32_t& aCol, + nsString* aDescription) +{ + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + acc->ColDescription(aCol, *aDescription); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableRowDescription(const uint64_t& aID, + const uint32_t& aRow, + nsString* aDescription) +{ + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + acc->RowDescription(aRow, *aDescription); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableColumnSelected(const uint64_t& aID, + const uint32_t& aCol, + bool* aSelected) +{ + *aSelected = false; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + *aSelected = acc->IsColSelected(aCol); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableRowSelected(const uint64_t& aID, + const uint32_t& aRow, + bool* aSelected) +{ + *aSelected = false; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + *aSelected = acc->IsRowSelected(aRow); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableCellSelected(const uint64_t& aID, + const uint32_t& aRow, + const uint32_t& aCol, + bool* aSelected) +{ + *aSelected = false; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + *aSelected = acc->IsCellSelected(aRow, aCol); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableSelectedCellCount(const uint64_t& aID, + uint32_t* aSelectedCells) +{ + *aSelectedCells = 0; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + *aSelectedCells = acc->SelectedCellCount(); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableSelectedColumnCount(const uint64_t& aID, + uint32_t* aSelectedColumns) +{ + *aSelectedColumns = 0; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + *aSelectedColumns = acc->SelectedColCount(); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableSelectedRowCount(const uint64_t& aID, + uint32_t* aSelectedRows) +{ + *aSelectedRows = 0; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + *aSelectedRows = acc->SelectedRowCount(); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableSelectedCells(const uint64_t& aID, + nsTArray<uint64_t>* aCellIDs) +{ + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + AutoTArray<Accessible*, 30> cells; + acc->SelectedCells(&cells); + aCellIDs->SetCapacity(cells.Length()); + for (uint32_t i = 0; i < cells.Length(); ++i) { + aCellIDs->AppendElement( + reinterpret_cast<uint64_t>(cells[i]->UniqueID())); + } + } + + return true; +} + +bool +DocAccessibleChild::RecvTableSelectedCellIndices(const uint64_t& aID, + nsTArray<uint32_t>* aCellIndices) +{ + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + acc->SelectedCellIndices(aCellIndices); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableSelectedColumnIndices(const uint64_t& aID, + nsTArray<uint32_t>* aColumnIndices) +{ + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + acc->SelectedColIndices(aColumnIndices); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableSelectedRowIndices(const uint64_t& aID, + nsTArray<uint32_t>* aRowIndices) +{ + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + acc->SelectedRowIndices(aRowIndices); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableSelectColumn(const uint64_t& aID, + const uint32_t& aCol) +{ + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + acc->SelectCol(aCol); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableSelectRow(const uint64_t& aID, + const uint32_t& aRow) +{ + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + acc->SelectRow(aRow); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableUnselectColumn(const uint64_t& aID, + const uint32_t& aCol) +{ + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + acc->UnselectCol(aCol); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableUnselectRow(const uint64_t& aID, + const uint32_t& aRow) +{ + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + acc->UnselectRow(aRow); + } + + return true; +} + +bool +DocAccessibleChild::RecvTableIsProbablyForLayout(const uint64_t& aID, + bool* aForLayout) +{ + *aForLayout = false; + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + *aForLayout = acc->IsProbablyLayoutTable(); + } + + return true; +} + +bool +DocAccessibleChild::RecvAtkTableColumnHeader(const uint64_t& aID, + const int32_t& aCol, + uint64_t* aHeader, + bool* aOk) +{ + *aHeader = 0; + *aOk = false; + +#ifdef MOZ_ACCESSIBILITY_ATK + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + Accessible* header = AccessibleWrap::GetColumnHeader(acc, aCol); + if (header) { + *aHeader = reinterpret_cast<uint64_t>(header->UniqueID()); + *aOk = true; + } + } +#endif + + return true; +} + +bool +DocAccessibleChild::RecvAtkTableRowHeader(const uint64_t& aID, + const int32_t& aRow, + uint64_t* aHeader, + bool* aOk) +{ + *aHeader = 0; + *aOk = false; + +#ifdef MOZ_ACCESSIBILITY_ATK + TableAccessible* acc = IdToTableAccessible(aID); + if (acc) { + Accessible* header = AccessibleWrap::GetRowHeader(acc, aRow); + if (header) { + *aHeader = reinterpret_cast<uint64_t>(header->UniqueID()); + *aOk = true; + } + } +#endif + + return true; +} + +bool +DocAccessibleChild::RecvSelectedItems(const uint64_t& aID, + nsTArray<uint64_t>* aSelectedItemIDs) +{ + Accessible* acc = IdToAccessibleSelect(aID); + if (acc) { + AutoTArray<Accessible*, 10> selectedItems; + acc->SelectedItems(&selectedItems); + aSelectedItemIDs->SetCapacity(selectedItems.Length()); + for (size_t i = 0; i < selectedItems.Length(); ++i) { + aSelectedItemIDs->AppendElement( + reinterpret_cast<uint64_t>(selectedItems[i]->UniqueID())); + } + } + + return true; +} + +bool +DocAccessibleChild::RecvSelectedItemCount(const uint64_t& aID, + uint32_t* aCount) +{ + *aCount = 0; + Accessible* acc = IdToAccessibleSelect(aID); + if (acc) { + *aCount = acc->SelectedItemCount(); + } + + return true; +} + +bool +DocAccessibleChild::RecvGetSelectedItem(const uint64_t& aID, + const uint32_t& aIndex, + uint64_t* aSelected, + bool* aOk) +{ + *aSelected = 0; + *aOk = false; + Accessible* acc = IdToAccessibleSelect(aID); + if (acc) { + Accessible* item = acc->GetSelectedItem(aIndex); + if (item) { + *aSelected = reinterpret_cast<uint64_t>(item->UniqueID()); + *aOk = true; + } + } + + return true; +} + +bool +DocAccessibleChild::RecvIsItemSelected(const uint64_t& aID, + const uint32_t& aIndex, + bool* aSelected) +{ + *aSelected = false; + Accessible* acc = IdToAccessibleSelect(aID); + if (acc) { + *aSelected = acc->IsItemSelected(aIndex); + } + + return true; +} + +bool +DocAccessibleChild::RecvAddItemToSelection(const uint64_t& aID, + const uint32_t& aIndex, + bool* aSuccess) +{ + *aSuccess = false; + Accessible* acc = IdToAccessibleSelect(aID); + if (acc) { + *aSuccess = acc->AddItemToSelection(aIndex); + } + + return true; +} + +bool +DocAccessibleChild::RecvRemoveItemFromSelection(const uint64_t& aID, + const uint32_t& aIndex, + bool* aSuccess) +{ + *aSuccess = false; + Accessible* acc = IdToAccessibleSelect(aID); + if (acc) { + *aSuccess = acc->RemoveItemFromSelection(aIndex); + } + + return true; +} + +bool +DocAccessibleChild::RecvSelectAll(const uint64_t& aID, + bool* aSuccess) +{ + *aSuccess = false; + Accessible* acc = IdToAccessibleSelect(aID); + if (acc) { + *aSuccess = acc->SelectAll(); + } + + return true; +} + +bool +DocAccessibleChild::RecvUnselectAll(const uint64_t& aID, + bool* aSuccess) +{ + *aSuccess = false; + Accessible* acc = IdToAccessibleSelect(aID); + if (acc) { + *aSuccess = acc->UnselectAll(); + } + + return true; +} + +bool +DocAccessibleChild::RecvTakeSelection(const uint64_t& aID) +{ + Accessible* acc = IdToAccessible(aID); + if (acc) { + acc->TakeSelection(); + } + + return true; +} + +bool +DocAccessibleChild::RecvSetSelected(const uint64_t& aID, const bool& aSelect) +{ + Accessible* acc = IdToAccessible(aID); + if (acc) { + acc->SetSelected(aSelect); + } + + return true; +} + +bool +DocAccessibleChild::RecvDoAction(const uint64_t& aID, + const uint8_t& aIndex, + bool* aSuccess) +{ + *aSuccess = false; + Accessible* acc = IdToAccessible(aID); + if (acc) { + *aSuccess = acc->DoAction(aIndex); + } + + return true; +} + +bool +DocAccessibleChild::RecvActionCount(const uint64_t& aID, + uint8_t* aCount) +{ + *aCount = 0; + Accessible* acc = IdToAccessible(aID); + if (acc) { + *aCount = acc->ActionCount(); + } + + return true; +} + +bool +DocAccessibleChild::RecvActionDescriptionAt(const uint64_t& aID, + const uint8_t& aIndex, + nsString* aDescription) +{ + Accessible* acc = IdToAccessible(aID); + if (acc) { + acc->ActionDescriptionAt(aIndex, *aDescription); + } + + return true; +} + +bool +DocAccessibleChild::RecvActionNameAt(const uint64_t& aID, + const uint8_t& aIndex, + nsString* aName) +{ + Accessible* acc = IdToAccessible(aID); + if (acc) { + acc->ActionNameAt(aIndex, *aName); + } + + return true; +} + +bool +DocAccessibleChild::RecvAccessKey(const uint64_t& aID, + uint32_t* aKey, + uint32_t* aModifierMask) +{ + *aKey = 0; + *aModifierMask = 0; + Accessible* acc = IdToAccessible(aID); + if (acc) { + KeyBinding kb = acc->AccessKey(); + *aKey = kb.Key(); + *aModifierMask = kb.ModifierMask(); + } + + return true; +} + +bool +DocAccessibleChild::RecvKeyboardShortcut(const uint64_t& aID, + uint32_t* aKey, + uint32_t* aModifierMask) +{ + *aKey = 0; + *aModifierMask = 0; + Accessible* acc = IdToAccessible(aID); + if (acc) { + KeyBinding kb = acc->KeyboardShortcut(); + *aKey = kb.Key(); + *aModifierMask = kb.ModifierMask(); + } + + return true; +} + +bool +DocAccessibleChild::RecvAtkKeyBinding(const uint64_t& aID, + nsString* aResult) +{ +#ifdef MOZ_ACCESSIBILITY_ATK + Accessible* acc = IdToAccessible(aID); + if (acc) { + AccessibleWrap::GetKeyBinding(acc, *aResult); + } +#endif + return true; +} + +bool +DocAccessibleChild::RecvCurValue(const uint64_t& aID, + double* aValue) +{ + *aValue = UnspecifiedNaN<double>(); + Accessible* acc = IdToAccessible(aID); + if (acc) { + *aValue = acc->CurValue(); + } + + return true; +} + +bool +DocAccessibleChild::RecvSetCurValue(const uint64_t& aID, + const double& aValue, + bool* aRetVal) +{ + *aRetVal = false; + Accessible* acc = IdToAccessible(aID); + if (acc) { + *aRetVal = acc->SetCurValue(aValue); + } + + return true; +} + +bool +DocAccessibleChild::RecvMinValue(const uint64_t& aID, + double* aValue) +{ + *aValue = UnspecifiedNaN<double>(); + Accessible* acc = IdToAccessible(aID); + if (acc) { + *aValue = acc->MinValue(); + } + + return true; +} + +bool +DocAccessibleChild::RecvMaxValue(const uint64_t& aID, + double* aValue) +{ + *aValue = UnspecifiedNaN<double>(); + Accessible* acc = IdToAccessible(aID); + if (acc) { + *aValue = acc->MaxValue(); + } + + return true; +} + +bool +DocAccessibleChild::RecvStep(const uint64_t& aID, + double* aStep) +{ + *aStep = UnspecifiedNaN<double>(); + Accessible* acc = IdToAccessible(aID); + if (acc) { + *aStep = acc->Step(); + } + + return true; +} + +bool +DocAccessibleChild::RecvTakeFocus(const uint64_t& aID) +{ + Accessible* acc = IdToAccessible(aID); + if (acc) { + acc->TakeFocus(); + } + + return true; +} + +bool +DocAccessibleChild::RecvFocusedChild(const uint64_t& aID, + uint64_t* aChild, + bool* aOk) +{ + *aChild = 0; + *aOk = false; + Accessible* acc = IdToAccessible(aID); + if (acc) { + Accessible* child = acc->FocusedChild(); + if (child) { + *aChild = reinterpret_cast<uint64_t>(child->UniqueID()); + *aOk = true; + } + } + return true; +} + +bool +DocAccessibleChild::RecvLanguage(const uint64_t& aID, + nsString* aLocale) +{ + Accessible* acc = IdToAccessible(aID); + if (acc) { + acc->Language(*aLocale); + } + + return true; +} + +bool +DocAccessibleChild::RecvDocType(const uint64_t& aID, + nsString* aType) +{ + Accessible* acc = IdToAccessible(aID); + if (acc && acc->IsDoc()) { + acc->AsDoc()->DocType(*aType); + } + + return true; +} + +bool +DocAccessibleChild::RecvTitle(const uint64_t& aID, + nsString* aTitle) +{ + Accessible* acc = IdToAccessible(aID); + if (acc) { + mozilla::ErrorResult rv; + acc->GetContent()->GetTextContent(*aTitle, rv); + } + + return true; +} + +bool +DocAccessibleChild::RecvURL(const uint64_t& aID, + nsString* aURL) +{ + Accessible* acc = IdToAccessible(aID); + if (acc && acc->IsDoc()) { + acc->AsDoc()->URL(*aURL); + } + + return true; +} + +bool +DocAccessibleChild::RecvMimeType(const uint64_t& aID, + nsString* aMime) +{ + Accessible* acc = IdToAccessible(aID); + if (acc && acc->IsDoc()) { + acc->AsDoc()->MimeType(*aMime); + } + + return true; +} + +bool +DocAccessibleChild::RecvURLDocTypeMimeType(const uint64_t& aID, + nsString* aURL, + nsString* aDocType, + nsString* aMimeType) +{ + Accessible* acc = IdToAccessible(aID); + if (acc && acc->IsDoc()) { + DocAccessible* doc = acc->AsDoc(); + doc->URL(*aURL); + doc->DocType(*aDocType); + doc->MimeType(*aMimeType); + } + + return true; +} + +bool +DocAccessibleChild::RecvAccessibleAtPoint(const uint64_t& aID, + const int32_t& aX, + const int32_t& aY, + const bool& aNeedsScreenCoords, + const uint32_t& aWhich, + uint64_t* aResult, + bool* aOk) +{ + *aResult = 0; + *aOk = false; + Accessible* acc = IdToAccessible(aID); + if (acc && !acc->IsDefunct() && !nsAccUtils::MustPrune(acc)) { + int32_t x = aX; + int32_t y = aY; + if (aNeedsScreenCoords) { + nsIntPoint winCoords = + nsCoreUtils::GetScreenCoordsForWindow(acc->GetNode()); + x += winCoords.x; + y += winCoords.y; + } + + Accessible* result = + acc->ChildAtPoint(x, y, + static_cast<Accessible::EWhichChildAtPoint>(aWhich)); + if (result) { + *aResult = reinterpret_cast<uint64_t>(result->UniqueID()); + *aOk = true; + } + } + + return true; +} + +bool +DocAccessibleChild::RecvExtents(const uint64_t& aID, + const bool& aNeedsScreenCoords, + int32_t* aX, + int32_t* aY, + int32_t* aWidth, + int32_t* aHeight) +{ + *aX = 0; + *aY = 0; + *aWidth = 0; + *aHeight = 0; + Accessible* acc = IdToAccessible(aID); + if (acc && !acc->IsDefunct()) { + nsIntRect screenRect = acc->Bounds(); + if (!screenRect.IsEmpty()) { + if (aNeedsScreenCoords) { + nsIntPoint winCoords = + nsCoreUtils::GetScreenCoordsForWindow(acc->GetNode()); + screenRect.x -= winCoords.x; + screenRect.y -= winCoords.y; + } + + *aX = screenRect.x; + *aY = screenRect.y; + *aWidth = screenRect.width; + *aHeight = screenRect.height; + } + } + return true; +} + +bool +DocAccessibleChild::RecvDOMNodeID(const uint64_t& aID, nsString* aDOMNodeID) +{ + Accessible* acc = IdToAccessible(aID); + if (!acc) { + return true; + } + + nsIContent* content = acc->GetContent(); + if (!content) { + return true; + } + + nsIAtom* id = content->GetID(); + if (id) { + id->ToString(*aDOMNodeID); + } + + return true; +} + +} +} diff --git a/accessible/ipc/other/DocAccessibleChild.h b/accessible/ipc/other/DocAccessibleChild.h new file mode 100644 index 0000000000..7c9d61da7f --- /dev/null +++ b/accessible/ipc/other/DocAccessibleChild.h @@ -0,0 +1,489 @@ +/* -*- 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/. */ + +#ifndef mozilla_a11y_DocAccessibleChild_h +#define mozilla_a11y_DocAccessibleChild_h + +#include "mozilla/a11y/DocAccessibleChildBase.h" + +namespace mozilla { +namespace a11y { + +class Accessible; +class HyperTextAccessible; +class TextLeafAccessible; +class ImageAccessible; +class TableAccessible; +class TableCellAccessible; + +/* + * These objects handle content side communication for an accessible document, + * and their lifetime is the same as the document they represent. + */ +class DocAccessibleChild : public DocAccessibleChildBase +{ +public: + explicit DocAccessibleChild(DocAccessible* aDoc) + : DocAccessibleChildBase(aDoc) + { + MOZ_COUNT_CTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase); + } + + ~DocAccessibleChild() + { + MOZ_COUNT_DTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase); + } + + /* + * Return the state for the accessible with given ID. + */ + virtual bool RecvState(const uint64_t& aID, uint64_t* aState) override; + + /* + * Return the native state for the accessible with given ID. + */ + virtual bool RecvNativeState(const uint64_t& aID, uint64_t* aState) override; + + /* + * Get the name for the accessible with given id. + */ + virtual bool RecvName(const uint64_t& aID, nsString* aName) override; + + virtual bool RecvValue(const uint64_t& aID, nsString* aValue) override; + + virtual bool RecvHelp(const uint64_t& aID, nsString* aHelp) override; + + /* + * Get the description for the accessible with given id. + */ + virtual bool RecvDescription(const uint64_t& aID, nsString* aDesc) override; + virtual bool RecvRelationByType(const uint64_t& aID, const uint32_t& aType, + nsTArray<uint64_t>* aTargets) override; + virtual bool RecvRelations(const uint64_t& aID, + nsTArray<RelationTargets>* aRelations) + override; + + virtual bool RecvIsSearchbox(const uint64_t& aID, bool* aRetVal) override; + + virtual bool RecvLandmarkRole(const uint64_t& aID, nsString* aLandmark) override; + + virtual bool RecvARIARoleAtom(const uint64_t& aID, nsString* aRole) override; + + virtual bool RecvGetLevelInternal(const uint64_t& aID, int32_t* aLevel) override; + + virtual bool RecvAttributes(const uint64_t& aID, + nsTArray<Attribute> *aAttributes) override; + virtual bool RecvScrollTo(const uint64_t& aID, const uint32_t& aScrollType) + override; + virtual bool RecvScrollToPoint(const uint64_t& aID, + const uint32_t& aScrollType, + const int32_t& aX, const int32_t& aY) override; + + virtual bool RecvCaretLineNumber(const uint64_t& aID, int32_t* aLineNumber) + override; + virtual bool RecvCaretOffset(const uint64_t& aID, int32_t* aOffset) + override; + virtual bool RecvSetCaretOffset(const uint64_t& aID, const int32_t& aOffset) + override; + + virtual bool RecvCharacterCount(const uint64_t& aID, int32_t* aCount) + override; + virtual bool RecvSelectionCount(const uint64_t& aID, int32_t* aCount) + override; + + virtual bool RecvTextSubstring(const uint64_t& aID, + const int32_t& aStartOffset, + const int32_t& aEndOffset, nsString* aText, + bool* aValid) override; + + virtual bool RecvGetTextAfterOffset(const uint64_t& aID, + const int32_t& aOffset, + const int32_t& aBoundaryType, + nsString* aText, int32_t* aStartOffset, + int32_t* aEndOffset) override; + virtual bool RecvGetTextAtOffset(const uint64_t& aID, + const int32_t& aOffset, + const int32_t& aBoundaryType, + nsString* aText, int32_t* aStartOffset, + int32_t* aEndOffset) override; + virtual bool RecvGetTextBeforeOffset(const uint64_t& aID, + const int32_t& aOffset, + const int32_t& aBoundaryType, + nsString* aText, int32_t* aStartOffset, + int32_t* aEndOffset) override; + + virtual bool RecvCharAt(const uint64_t& aID, + const int32_t& aOffset, + uint16_t* aChar) override; + + virtual bool RecvTextAttributes(const uint64_t& aID, + const bool& aIncludeDefAttrs, + const int32_t& aOffset, + nsTArray<Attribute>* aAttributes, + int32_t* aStartOffset, + int32_t* aEndOffset) + override; + + virtual bool RecvDefaultTextAttributes(const uint64_t& aID, + nsTArray<Attribute>* aAttributes) + override; + + virtual bool RecvTextBounds(const uint64_t& aID, + const int32_t& aStartOffset, + const int32_t& aEndOffset, + const uint32_t& aCoordType, + nsIntRect* aRetVal) override; + + virtual bool RecvCharBounds(const uint64_t& aID, + const int32_t& aOffset, + const uint32_t& aCoordType, + nsIntRect* aRetVal) override; + + virtual bool RecvOffsetAtPoint(const uint64_t& aID, + const int32_t& aX, + const int32_t& aY, + const uint32_t& aCoordType, + int32_t* aRetVal) override; + + virtual bool RecvSelectionBoundsAt(const uint64_t& aID, + const int32_t& aSelectionNum, + bool* aSucceeded, + nsString* aData, + int32_t* aStartOffset, + int32_t* aEndOffset) override; + + virtual bool RecvSetSelectionBoundsAt(const uint64_t& aID, + const int32_t& aSelectionNum, + const int32_t& aStartOffset, + const int32_t& aEndOffset, + bool* aSucceeded) override; + + virtual bool RecvAddToSelection(const uint64_t& aID, + const int32_t& aStartOffset, + const int32_t& aEndOffset, + bool* aSucceeded) override; + + virtual bool RecvRemoveFromSelection(const uint64_t& aID, + const int32_t& aSelectionNum, + bool* aSucceeded) override; + + virtual bool RecvScrollSubstringTo(const uint64_t& aID, + const int32_t& aStartOffset, + const int32_t& aEndOffset, + const uint32_t& aScrollType) override; + + virtual bool RecvScrollSubstringToPoint(const uint64_t& aID, + const int32_t& aStartOffset, + const int32_t& aEndOffset, + const uint32_t& aCoordinateType, + const int32_t& aX, + const int32_t& aY) override; + + virtual bool RecvText(const uint64_t& aID, + nsString* aText) override; + + virtual bool RecvReplaceText(const uint64_t& aID, + const nsString& aText) override; + + virtual bool RecvInsertText(const uint64_t& aID, + const nsString& aText, + const int32_t& aPosition, bool* aValid) override; + + virtual bool RecvCopyText(const uint64_t& aID, + const int32_t& aStartPos, + const int32_t& aEndPos, bool* aValid) override; + + virtual bool RecvCutText(const uint64_t& aID, + const int32_t& aStartPos, + const int32_t& aEndPos, bool* aValid) override; + + virtual bool RecvDeleteText(const uint64_t& aID, + const int32_t& aStartPos, + const int32_t& aEndPos, bool* aValid) override; + + virtual bool RecvPasteText(const uint64_t& aID, + const int32_t& aPosition, bool* aValid) override; + + virtual bool RecvImagePosition(const uint64_t& aID, + const uint32_t& aCoordType, + nsIntPoint* aRetVal) override; + + virtual bool RecvImageSize(const uint64_t& aID, + nsIntSize* aRetVal) override; + + virtual bool RecvStartOffset(const uint64_t& aID, + uint32_t* aRetVal, + bool* aOk) override; + virtual bool RecvEndOffset(const uint64_t& aID, + uint32_t* aRetVal, + bool* aOk) override; + virtual bool RecvIsLinkValid(const uint64_t& aID, + bool* aRetVal) override; + virtual bool RecvAnchorCount(const uint64_t& aID, + uint32_t* aRetVal, bool* aOk) override; + virtual bool RecvAnchorURIAt(const uint64_t& aID, + const uint32_t& aIndex, + nsCString* aURI, + bool* aOk) override; + virtual bool RecvAnchorAt(const uint64_t& aID, + const uint32_t& aIndex, + uint64_t* aIDOfAnchor, + bool* aOk) override; + + virtual bool RecvLinkCount(const uint64_t& aID, + uint32_t* aCount) override; + + virtual bool RecvLinkAt(const uint64_t& aID, + const uint32_t& aIndex, + uint64_t* aIDOfLink, + bool* aOk) override; + + virtual bool RecvLinkIndexOf(const uint64_t& aID, + const uint64_t& aLinkID, + int32_t* aIndex) override; + + virtual bool RecvLinkIndexAtOffset(const uint64_t& aID, + const uint32_t& aOffset, + int32_t* aIndex) override; + + virtual bool RecvTableOfACell(const uint64_t& aID, + uint64_t* aTableID, + bool* aOk) override; + + virtual bool RecvColIdx(const uint64_t& aID, uint32_t* aIndex) override; + + virtual bool RecvRowIdx(const uint64_t& aID, uint32_t* aIndex) override; + + virtual bool RecvColExtent(const uint64_t& aID, uint32_t* aExtent) override; + + virtual bool RecvGetPosition(const uint64_t& aID, + uint32_t* aColIdx, uint32_t* aRowIdx) override; + + virtual bool RecvGetColRowExtents(const uint64_t& aID, + uint32_t* aColIdx, uint32_t* aRowIdx, + uint32_t* aColExtent, uint32_t* aRowExtent) override; + + virtual bool RecvRowExtent(const uint64_t& aID, uint32_t* aExtent) override; + + virtual bool RecvColHeaderCells(const uint64_t& aID, + nsTArray<uint64_t>* aCells) override; + + virtual bool RecvRowHeaderCells(const uint64_t& aID, + nsTArray<uint64_t>* aCells) override; + + virtual bool RecvIsCellSelected(const uint64_t& aID, + bool* aSelected) override; + + virtual bool RecvTableCaption(const uint64_t& aID, + uint64_t* aCaptionID, + bool* aOk) override; + virtual bool RecvTableSummary(const uint64_t& aID, + nsString* aSummary) override; + virtual bool RecvTableColumnCount(const uint64_t& aID, + uint32_t* aColCount) override; + virtual bool RecvTableRowCount(const uint64_t& aID, + uint32_t* aRowCount) override; + virtual bool RecvTableCellAt(const uint64_t& aID, + const uint32_t& aRow, + const uint32_t& aCol, + uint64_t* aCellID, + bool* aOk) override; + virtual bool RecvTableCellIndexAt(const uint64_t& aID, + const uint32_t& aRow, + const uint32_t& aCol, + int32_t* aIndex) override; + virtual bool RecvTableColumnIndexAt(const uint64_t& aID, + const uint32_t& aCellIndex, + int32_t* aCol) override; + virtual bool RecvTableRowIndexAt(const uint64_t& aID, + const uint32_t& aCellIndex, + int32_t* aRow) override; + virtual bool RecvTableRowAndColumnIndicesAt(const uint64_t& aID, + const uint32_t& aCellIndex, + int32_t* aRow, + int32_t* aCol) override; + virtual bool RecvTableColumnExtentAt(const uint64_t& aID, + const uint32_t& aRow, + const uint32_t& aCol, + uint32_t* aExtent) override; + virtual bool RecvTableRowExtentAt(const uint64_t& aID, + const uint32_t& aRow, + const uint32_t& aCol, + uint32_t* aExtent) override; + virtual bool RecvTableColumnDescription(const uint64_t& aID, + const uint32_t& aCol, + nsString* aDescription) override; + virtual bool RecvTableRowDescription(const uint64_t& aID, + const uint32_t& aRow, + nsString* aDescription) override; + virtual bool RecvTableColumnSelected(const uint64_t& aID, + const uint32_t& aCol, + bool* aSelected) override; + virtual bool RecvTableRowSelected(const uint64_t& aID, + const uint32_t& aRow, + bool* aSelected) override; + virtual bool RecvTableCellSelected(const uint64_t& aID, + const uint32_t& aRow, + const uint32_t& aCol, + bool* aSelected) override; + virtual bool RecvTableSelectedCellCount(const uint64_t& aID, + uint32_t* aSelectedCells) override; + virtual bool RecvTableSelectedColumnCount(const uint64_t& aID, + uint32_t* aSelectedColumns) override; + virtual bool RecvTableSelectedRowCount(const uint64_t& aID, + uint32_t* aSelectedRows) override; + virtual bool RecvTableSelectedCells(const uint64_t& aID, + nsTArray<uint64_t>* aCellIDs) override; + virtual bool RecvTableSelectedCellIndices(const uint64_t& aID, + nsTArray<uint32_t>* aCellIndices) override; + virtual bool RecvTableSelectedColumnIndices(const uint64_t& aID, + nsTArray<uint32_t>* aColumnIndices) override; + virtual bool RecvTableSelectedRowIndices(const uint64_t& aID, + nsTArray<uint32_t>* aRowIndices) override; + virtual bool RecvTableSelectColumn(const uint64_t& aID, + const uint32_t& aCol) override; + virtual bool RecvTableSelectRow(const uint64_t& aID, + const uint32_t& aRow) override; + virtual bool RecvTableUnselectColumn(const uint64_t& aID, + const uint32_t& aCol) override; + virtual bool RecvTableUnselectRow(const uint64_t& aID, + const uint32_t& aRow) override; + virtual bool RecvTableIsProbablyForLayout(const uint64_t& aID, + bool* aForLayout) override; + virtual bool RecvAtkTableColumnHeader(const uint64_t& aID, + const int32_t& aCol, + uint64_t* aHeader, + bool* aOk) override; + virtual bool RecvAtkTableRowHeader(const uint64_t& aID, + const int32_t& aRow, + uint64_t* aHeader, + bool* aOk) override; + + virtual bool RecvSelectedItems(const uint64_t& aID, + nsTArray<uint64_t>* aSelectedItemIDs) override; + + virtual bool RecvSelectedItemCount(const uint64_t& aID, + uint32_t* aCount) override; + + virtual bool RecvGetSelectedItem(const uint64_t& aID, + const uint32_t& aIndex, + uint64_t* aSelected, + bool* aOk) override; + + virtual bool RecvIsItemSelected(const uint64_t& aID, + const uint32_t& aIndex, + bool* aSelected) override; + + virtual bool RecvAddItemToSelection(const uint64_t& aID, + const uint32_t& aIndex, + bool* aSuccess) override; + + virtual bool RecvRemoveItemFromSelection(const uint64_t& aID, + const uint32_t& aIndex, + bool* aSuccess) override; + + virtual bool RecvSelectAll(const uint64_t& aID, + bool* aSuccess) override; + + virtual bool RecvUnselectAll(const uint64_t& aID, + bool* aSuccess) override; + + virtual bool RecvTakeSelection(const uint64_t& aID) override; + virtual bool RecvSetSelected(const uint64_t& aID, + const bool& aSelect) override; + + virtual bool RecvDoAction(const uint64_t& aID, + const uint8_t& aIndex, + bool* aSuccess) override; + + virtual bool RecvActionCount(const uint64_t& aID, + uint8_t* aCount) override; + + virtual bool RecvActionDescriptionAt(const uint64_t& aID, + const uint8_t& aIndex, + nsString* aDescription) override; + + virtual bool RecvActionNameAt(const uint64_t& aID, + const uint8_t& aIndex, + nsString* aName) override; + + virtual bool RecvAccessKey(const uint64_t& aID, + uint32_t* aKey, + uint32_t* aModifierMask) override; + + virtual bool RecvKeyboardShortcut(const uint64_t& aID, + uint32_t* aKey, + uint32_t* aModifierMask) override; + + virtual bool RecvAtkKeyBinding(const uint64_t& aID, + nsString* aResult) override; + + virtual bool RecvCurValue(const uint64_t& aID, + double* aValue) override; + + virtual bool RecvSetCurValue(const uint64_t& aID, + const double& aValue, + bool* aRetVal) override; + + virtual bool RecvMinValue(const uint64_t& aID, + double* aValue) override; + + virtual bool RecvMaxValue(const uint64_t& aID, + double* aValue) override; + + virtual bool RecvStep(const uint64_t& aID, + double* aStep) override; + + virtual bool RecvTakeFocus(const uint64_t& aID) override; + + virtual bool RecvFocusedChild(const uint64_t& aID, + uint64_t* aChild, + bool* aOk) override; + + virtual bool RecvLanguage(const uint64_t& aID, nsString* aLocale) override; + virtual bool RecvDocType(const uint64_t& aID, nsString* aType) override; + virtual bool RecvTitle(const uint64_t& aID, nsString* aTitle) override; + virtual bool RecvURL(const uint64_t& aID, nsString* aURL) override; + virtual bool RecvMimeType(const uint64_t& aID, nsString* aMime) override; + virtual bool RecvURLDocTypeMimeType(const uint64_t& aID, + nsString* aURL, + nsString* aDocType, + nsString* aMimeType) override; + + virtual bool RecvAccessibleAtPoint(const uint64_t& aID, + const int32_t& aX, + const int32_t& aY, + const bool& aNeedsScreenCoords, + const uint32_t& aWhich, + uint64_t* aResult, + bool* aOk) override; + + virtual bool RecvExtents(const uint64_t& aID, + const bool& aNeedsScreenCoords, + int32_t* aX, + int32_t* aY, + int32_t* aWidth, + int32_t* aHeight) override; + virtual bool RecvDOMNodeID(const uint64_t& aID, nsString* aDOMNodeID) override; +private: + + Accessible* IdToAccessible(const uint64_t& aID) const; + Accessible* IdToAccessibleLink(const uint64_t& aID) const; + Accessible* IdToAccessibleSelect(const uint64_t& aID) const; + HyperTextAccessible* IdToHyperTextAccessible(const uint64_t& aID) const; + TextLeafAccessible* IdToTextLeafAccessible(const uint64_t& aID) const; + ImageAccessible* IdToImageAccessible(const uint64_t& aID) const; + TableCellAccessible* IdToTableCellAccessible(const uint64_t& aID) const; + TableAccessible* IdToTableAccessible(const uint64_t& aID) const; + + bool PersistentPropertiesToArray(nsIPersistentProperties* aProps, + nsTArray<Attribute>* aAttributes); +}; + +} +} + +#endif diff --git a/accessible/ipc/other/PDocAccessible.ipdl b/accessible/ipc/other/PDocAccessible.ipdl new file mode 100644 index 0000000000..1885ed7863 --- /dev/null +++ b/accessible/ipc/other/PDocAccessible.ipdl @@ -0,0 +1,264 @@ +/* -*- 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 protocol PFileDescriptorSet; +include protocol PBrowser; + +include "mozilla/GfxMessageUtils.h"; + +using nsIntRect from "nsRect.h"; +using mozilla::gfx::IntSize from "mozilla/gfx/Point.h"; +using mozilla::gfx::IntPoint from "mozilla/gfx/Point.h"; + +namespace mozilla { +namespace a11y { + +struct AccessibleData +{ + uint64_t ID; + uint32_t Role; + uint32_t ChildrenCount; + uint32_t Interfaces; +}; + +struct ShowEventData +{ + uint64_t ID; + uint32_t Idx; + AccessibleData[] NewTree; +}; + +struct Attribute +{ + nsCString Name; + nsString Value; +}; + +struct RelationTargets +{ + uint32_t Type; + uint64_t[] Targets; +}; + +nested(upto inside_sync) sync protocol PDocAccessible +{ + manager PBrowser; + +parent: + async Shutdown(); + + /* + * Notify the parent process the document in the child process is firing an + * event. + */ + async Event(uint64_t aID, uint32_t type); + async ShowEvent(ShowEventData data, bool aFromuser); + async HideEvent(uint64_t aRootID, bool aFromUser); + async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled); + async CaretMoveEvent(uint64_t aID, int32_t aOffset); + async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen, + bool aIsInsert, bool aFromUser); + async SelectionEvent(uint64_t aID, uint64_t aWidgetID, uint32_t aType); + async RoleChangedEvent(uint32_t aRole); + + /* + * Tell the parent document to bind the existing document as a new child + * document. + */ + async BindChildDoc(PDocAccessible aChildDoc, uint64_t aID); + +child: + async __delete__(); + + // Accessible + nested(inside_sync) sync State(uint64_t aID) returns(uint64_t states); + nested(inside_sync) sync NativeState(uint64_t aID) returns(uint64_t states); + nested(inside_sync) sync Name(uint64_t aID) returns(nsString name); + nested(inside_sync) sync Value(uint64_t aID) returns(nsString value); + nested(inside_sync) sync Help(uint64_t aID) returns(nsString help); + nested(inside_sync) sync Description(uint64_t aID) returns(nsString desc); + nested(inside_sync) sync Attributes(uint64_t aID) returns(Attribute[] attributes); + nested(inside_sync) sync RelationByType(uint64_t aID, uint32_t aRelationType) + returns(uint64_t[] targets); + nested(inside_sync) sync Relations(uint64_t aID) returns(RelationTargets[] relations); + nested(inside_sync) sync IsSearchbox(uint64_t aID) returns(bool retval); + nested(inside_sync) sync LandmarkRole(uint64_t aID) returns(nsString landmark); + nested(inside_sync) sync ARIARoleAtom(uint64_t aID) returns(nsString role); + nested(inside_sync) sync GetLevelInternal(uint64_t aID) returns(int32_t aLevel); + async ScrollTo(uint64_t aID, uint32_t aScrollType); + async ScrollToPoint(uint64_t aID, uint32_t aScrollType, int32_t aX, + int32_t aY); + + // AccessibleText + + // TextSubstring is getText in IDL. + nested(inside_sync) sync CaretLineNumber(uint64_t aID) returns(int32_t aLineNumber); + nested(inside_sync) sync CaretOffset(uint64_t aID) returns(int32_t aOffset); + async SetCaretOffset(uint64_t aID, int32_t aOffset); + nested(inside_sync) sync CharacterCount(uint64_t aID) returns(int32_t aCount); + nested(inside_sync) sync SelectionCount(uint64_t aID) returns(int32_t aCount); + nested(inside_sync) sync TextSubstring(uint64_t aID, int32_t aStartOffset, int32_t + aEndOffset) returns(nsString aText, bool aValid); + nested(inside_sync) sync GetTextAfterOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType) + returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset); + nested(inside_sync) sync GetTextAtOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType) + returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset); + + nested(inside_sync) sync GetTextBeforeOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType) + returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset); + nested(inside_sync) sync CharAt(uint64_t aID, int32_t aOffset) returns(uint16_t aChar); + + nested(inside_sync) sync TextAttributes(uint64_t aID, bool aIncludeDefAttrs, int32_t aOffset) + returns(Attribute[] aAttributes, int32_t aStartOffset, int32_t aEndOffset); + nested(inside_sync) sync DefaultTextAttributes(uint64_t aID) returns(Attribute[] aAttributes); + + nested(inside_sync) sync TextBounds(uint64_t aID, int32_t aStartOffset, int32_t aEndOffset, + uint32_t aCoordType) + returns(nsIntRect aRetVal); + nested(inside_sync) sync CharBounds(uint64_t aID, int32_t aOffset, uint32_t aCoordType) + returns(nsIntRect aRetVal); + + nested(inside_sync) sync OffsetAtPoint(uint64_t aID, int32_t aX, int32_t aY, uint32_t aCoordType) + returns(int32_t aRetVal); + + nested(inside_sync) sync SelectionBoundsAt(uint64_t aID, int32_t aSelectionNum) + returns(bool aSucceeded, nsString aData, int32_t aStartOffset, int32_t aEndOffset); + nested(inside_sync) sync SetSelectionBoundsAt(uint64_t aID, int32_t aSelectionNum, + int32_t aStartOffset, int32_t aEndOffset) + returns(bool aSucceeded); + nested(inside_sync) sync AddToSelection(uint64_t aID, int32_t aStartOffset, int32_t aEndOffset) + returns(bool aSucceeded); + nested(inside_sync) sync RemoveFromSelection(uint64_t aID, int32_t aSelectionNum) + returns(bool aSucceeded); + + async ScrollSubstringTo(uint64_t aID, int32_t aStartOffset, int32_t aEndOffset, + uint32_t aScrollType); + async ScrollSubstringToPoint(uint64_t aID, + int32_t aStartOffset, + int32_t aEndOffset, + uint32_t aCoordinateType, + int32_t aX, int32_t aY); + + nested(inside_sync) sync Text(uint64_t aID) returns(nsString aText); + nested(inside_sync) sync ReplaceText(uint64_t aID, nsString aText); + nested(inside_sync) sync InsertText(uint64_t aID, nsString aText, int32_t aPosition) + returns(bool aValid); + nested(inside_sync) sync CopyText(uint64_t aID, int32_t aStartPos, int32_t aEndPos) + returns(bool aValid); + nested(inside_sync) sync CutText(uint64_t aID, int32_t aStartPos, int32_t aEndPos) + returns(bool aValid); + nested(inside_sync) sync DeleteText(uint64_t aID, int32_t aStartPos, int32_t aEndPos) + returns(bool aValid); + nested(inside_sync) sync PasteText(uint64_t aID, int32_t aPosition) + returns(bool aValid); + + nested(inside_sync) sync ImagePosition(uint64_t aID, uint32_t aCoordType) returns(IntPoint aRetVal); + nested(inside_sync) sync ImageSize(uint64_t aID) returns(IntSize aRetVal); + + nested(inside_sync) sync StartOffset(uint64_t aID) returns(uint32_t aRetVal, bool aOk); + nested(inside_sync) sync EndOffset(uint64_t aID) returns(uint32_t aRetVal, bool aOk); + nested(inside_sync) sync IsLinkValid(uint64_t aID) returns(bool aRetVal); + nested(inside_sync) sync AnchorCount(uint64_t aID) returns(uint32_t aRetVal, bool aOk); + nested(inside_sync) sync AnchorURIAt(uint64_t aID, uint32_t aIndex) returns(nsCString aURI, bool aOk); + nested(inside_sync) sync AnchorAt(uint64_t aID, uint32_t aIndex) returns(uint64_t aIDOfAnchor, bool aOk); + + nested(inside_sync) sync LinkCount(uint64_t aID) returns(uint32_t aCount); + nested(inside_sync) sync LinkAt(uint64_t aID, uint32_t aIndex) returns(uint64_t aIDOfLink, bool aOk); + nested(inside_sync) sync LinkIndexOf(uint64_t aID, uint64_t aLinkID) returns(int32_t aIndex); + nested(inside_sync) sync LinkIndexAtOffset(uint64_t aID, uint32_t aOffset) returns(int32_t aIndex); + + nested(inside_sync) sync TableOfACell(uint64_t aID) returns(uint64_t aTableID, bool aOk); + nested(inside_sync) sync ColIdx(uint64_t aID) returns(uint32_t aIndex); + nested(inside_sync) sync RowIdx(uint64_t aID) returns(uint32_t aIndex); + nested(inside_sync) sync GetPosition(uint64_t aID) returns(uint32_t aRow, uint32_t aCol); + nested(inside_sync) sync ColExtent(uint64_t aID) returns(uint32_t aExtent); + nested(inside_sync) sync RowExtent(uint64_t aID) returns(uint32_t aExtent); + nested(inside_sync) sync GetColRowExtents(uint64_t aID) + returns(uint32_t aCol, uint32_t aRow, uint32_t aColExtent, uint32_t aRowExtent); + nested(inside_sync) sync ColHeaderCells(uint64_t aID) returns(uint64_t[] aCells); + nested(inside_sync) sync RowHeaderCells(uint64_t aID) returns(uint64_t[] aCells); + nested(inside_sync) sync IsCellSelected(uint64_t aID) returns(bool aSelected); + + nested(inside_sync) sync TableCaption(uint64_t aID) returns(uint64_t aCaptionID, bool aOk); + nested(inside_sync) sync TableSummary(uint64_t aID) returns(nsString aSummary); + nested(inside_sync) sync TableColumnCount(uint64_t aID) returns(uint32_t aColCount); + nested(inside_sync) sync TableRowCount(uint64_t aID) returns(uint32_t aRowCount); + nested(inside_sync) sync TableCellAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(uint64_t aCellID, bool aOk); + nested(inside_sync) sync TableCellIndexAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(int32_t aIndex); + nested(inside_sync) sync TableColumnIndexAt(uint64_t aID, uint32_t aCellIndex) returns(int32_t aCol); + nested(inside_sync) sync TableRowIndexAt(uint64_t aID, uint32_t aCellIndex) returns(int32_t aRow); + nested(inside_sync) sync TableRowAndColumnIndicesAt(uint64_t aID, uint32_t aCellIndex) returns(int32_t aRow, int32_t aCol); + nested(inside_sync) sync TableColumnExtentAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(uint32_t aExtent); + nested(inside_sync) sync TableRowExtentAt(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(uint32_t aExtent); + nested(inside_sync) sync TableColumnDescription(uint64_t aID, uint32_t aCol) returns(nsString aDescription); + nested(inside_sync) sync TableRowDescription(uint64_t aID, uint32_t aRow) returns(nsString aDescription); + nested(inside_sync) sync TableColumnSelected(uint64_t aID, uint32_t aCol) returns(bool aSelected); + nested(inside_sync) sync TableRowSelected(uint64_t aID, uint32_t aRow) returns(bool aSelected); + nested(inside_sync) sync TableCellSelected(uint64_t aID, uint32_t aRow, uint32_t aCol) returns(bool aSelected); + nested(inside_sync) sync TableSelectedCellCount(uint64_t aID) returns(uint32_t aSelectedCells); + nested(inside_sync) sync TableSelectedColumnCount(uint64_t aID) returns(uint32_t aSelectedColumns); + nested(inside_sync) sync TableSelectedRowCount(uint64_t aID) returns(uint32_t aSelectedRows); + nested(inside_sync) sync TableSelectedCells(uint64_t aID) returns(uint64_t[] aCellIDs); + nested(inside_sync) sync TableSelectedCellIndices(uint64_t aID) returns(uint32_t[] aCellIndeces); + nested(inside_sync) sync TableSelectedColumnIndices(uint64_t aID) returns(uint32_t[] aColumnIndeces); + nested(inside_sync) sync TableSelectedRowIndices(uint64_t aID) returns(uint32_t[] aRowIndeces); + nested(inside_sync) sync TableSelectColumn(uint64_t aID, uint32_t aCol); + nested(inside_sync) sync TableSelectRow(uint64_t aID, uint32_t aRow); + nested(inside_sync) sync TableUnselectColumn(uint64_t aID, uint32_t aCol); + nested(inside_sync) sync TableUnselectRow(uint64_t aID, uint32_t aRow); + nested(inside_sync) sync TableIsProbablyForLayout(uint64_t aID) returns(bool aForLayout); + nested(inside_sync) sync AtkTableColumnHeader(uint64_t aID, int32_t aCol) + returns(uint64_t aHeaderID, bool aOk); + nested(inside_sync) sync AtkTableRowHeader(uint64_t aID, int32_t aRow) + returns(uint64_t aHeaderID, bool aOk); + + nested(inside_sync) sync SelectedItems(uint64_t aID) returns(uint64_t[] aSelectedItemIDs); + nested(inside_sync) sync SelectedItemCount(uint64_t aID) returns(uint32_t aCount); + nested(inside_sync) sync GetSelectedItem(uint64_t aID, uint32_t aIndex) returns(uint64_t aSelected, bool aOk); + nested(inside_sync) sync IsItemSelected(uint64_t aID, uint32_t aIndex) returns(bool aSelected); + nested(inside_sync) sync AddItemToSelection(uint64_t aID, uint32_t aIndex) returns(bool aSuccess); + nested(inside_sync) sync RemoveItemFromSelection(uint64_t aID, uint32_t aIndex) returns(bool aSuccess); + nested(inside_sync) sync SelectAll(uint64_t aID) returns(bool aSuccess); + nested(inside_sync) sync UnselectAll(uint64_t aID) returns(bool aSuccess); + + async TakeSelection(uint64_t aID); + async SetSelected(uint64_t aID, bool aSelected); + + nested(inside_sync) sync DoAction(uint64_t aID, uint8_t aIndex) returns(bool aSuccess); + nested(inside_sync) sync ActionCount(uint64_t aID) returns(uint8_t aCount); + nested(inside_sync) sync ActionDescriptionAt(uint64_t aID, uint8_t aIndex) returns(nsString aDescription); + nested(inside_sync) sync ActionNameAt(uint64_t aID, uint8_t aIndex) returns(nsString aName); + nested(inside_sync) sync AccessKey(uint64_t aID) returns(uint32_t aKey, uint32_t aModifierMask); + nested(inside_sync) sync KeyboardShortcut(uint64_t aID) returns(uint32_t aKey, uint32_t aModifierMask); + nested(inside_sync) sync AtkKeyBinding(uint64_t aID) returns(nsString aResult); + + nested(inside_sync) sync CurValue(uint64_t aID) returns(double aValue); + nested(inside_sync) sync SetCurValue(uint64_t aID, double aValue) returns(bool aRetVal); + nested(inside_sync) sync MinValue(uint64_t aID) returns(double aValue); + nested(inside_sync) sync MaxValue(uint64_t aID) returns(double aValue); + nested(inside_sync) sync Step(uint64_t aID) returns(double aStep); + + async TakeFocus(uint64_t aID); + nested(inside_sync) sync FocusedChild(uint64_t aID) + returns(uint64_t aChild, bool aOk); + + nested(inside_sync) sync Language(uint64_t aID) returns(nsString aLocale); + nested(inside_sync) sync DocType(uint64_t aID) returns(nsString aType); + nested(inside_sync) sync Title(uint64_t aID) returns(nsString aTitle); + nested(inside_sync) sync URL(uint64_t aID) returns(nsString aURL); + nested(inside_sync) sync MimeType(uint64_t aID) returns(nsString aMime); + nested(inside_sync) sync URLDocTypeMimeType(uint64_t aID) returns(nsString aURL, nsString aDocType, nsString aMimeType); + + nested(inside_sync) sync AccessibleAtPoint(uint64_t aID, int32_t aX, int32_t aY, bool aNeedsScreenCoords, uint32_t aWhich) + returns(uint64_t aResult, bool aOk); + + nested(inside_sync) sync Extents(uint64_t aID, bool aNeedsScreenCoords) + returns(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight); + nested(inside_sync) sync DOMNodeID(uint64_t aID) returns(nsString aDOMNodeID); +}; + +} +} diff --git a/accessible/ipc/other/ProxyAccessible.cpp b/accessible/ipc/other/ProxyAccessible.cpp new file mode 100644 index 0000000000..2eb93dfdad --- /dev/null +++ b/accessible/ipc/other/ProxyAccessible.cpp @@ -0,0 +1,1080 @@ +/* -*- 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 "ProxyAccessible.h" +#include "mozilla/a11y/DocAccessibleParent.h" +#include "DocAccessible.h" +#include "mozilla/a11y/DocManager.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/TabParent.h" +#include "mozilla/Unused.h" +#include "mozilla/a11y/Platform.h" +#include "RelationType.h" +#include "mozilla/a11y/Role.h" +#include "xpcAccessibleDocument.h" + +namespace mozilla { +namespace a11y { + +uint64_t +ProxyAccessible::State() const +{ + uint64_t state = 0; + Unused << mDoc->SendState(mID, &state); + return state; +} + +uint64_t +ProxyAccessible::NativeState() const +{ + uint64_t state = 0; + Unused << mDoc->SendNativeState(mID, &state); + return state; +} + +void +ProxyAccessible::Name(nsString& aName) const +{ + Unused << mDoc->SendName(mID, &aName); +} + +void +ProxyAccessible::Value(nsString& aValue) const +{ + Unused << mDoc->SendValue(mID, &aValue); +} + +void +ProxyAccessible::Help(nsString& aHelp) const +{ + Unused << mDoc->SendHelp(mID, &aHelp); +} + +void +ProxyAccessible::Description(nsString& aDesc) const +{ + Unused << mDoc->SendDescription(mID, &aDesc); +} + +void +ProxyAccessible::Attributes(nsTArray<Attribute> *aAttrs) const +{ + Unused << mDoc->SendAttributes(mID, aAttrs); +} + +nsTArray<ProxyAccessible*> +ProxyAccessible::RelationByType(RelationType aType) const +{ + nsTArray<uint64_t> targetIDs; + Unused << mDoc->SendRelationByType(mID, static_cast<uint32_t>(aType), + &targetIDs); + + size_t targetCount = targetIDs.Length(); + nsTArray<ProxyAccessible*> targets(targetCount); + for (size_t i = 0; i < targetCount; i++) + if (ProxyAccessible* proxy = mDoc->GetAccessible(targetIDs[i])) + targets.AppendElement(proxy); + + return Move(targets); +} + +void +ProxyAccessible::Relations(nsTArray<RelationType>* aTypes, + nsTArray<nsTArray<ProxyAccessible*>>* aTargetSets) + const +{ + nsTArray<RelationTargets> ipcRelations; + Unused << mDoc->SendRelations(mID, &ipcRelations); + + size_t relationCount = ipcRelations.Length(); + aTypes->SetCapacity(relationCount); + aTargetSets->SetCapacity(relationCount); + for (size_t i = 0; i < relationCount; i++) { + uint32_t type = ipcRelations[i].Type(); + if (type > static_cast<uint32_t>(RelationType::LAST)) + continue; + + size_t targetCount = ipcRelations[i].Targets().Length(); + nsTArray<ProxyAccessible*> targets(targetCount); + for (size_t j = 0; j < targetCount; j++) + if (ProxyAccessible* proxy = mDoc->GetAccessible(ipcRelations[i].Targets()[j])) + targets.AppendElement(proxy); + + if (targets.IsEmpty()) + continue; + + aTargetSets->AppendElement(Move(targets)); + aTypes->AppendElement(static_cast<RelationType>(type)); + } +} + +bool +ProxyAccessible::IsSearchbox() const +{ + bool retVal = false; + Unused << mDoc->SendIsSearchbox(mID, &retVal); + return retVal; +} + +nsIAtom* +ProxyAccessible::LandmarkRole() const +{ + nsString landmark; + Unused << mDoc->SendLandmarkRole(mID, &landmark); + return NS_GetStaticAtom(landmark); +} + +nsIAtom* +ProxyAccessible::ARIARoleAtom() const +{ + nsString role; + Unused << mDoc->SendARIARoleAtom(mID, &role); + return NS_GetStaticAtom(role); +} + +int32_t +ProxyAccessible::GetLevelInternal() +{ + int32_t level = 0; + Unused << mDoc->SendGetLevelInternal(mID, &level); + return level; +} + +void +ProxyAccessible::ScrollTo(uint32_t aScrollType) +{ + Unused << mDoc->SendScrollTo(mID, aScrollType); +} + +void +ProxyAccessible::ScrollToPoint(uint32_t aScrollType, int32_t aX, int32_t aY) +{ + Unused << mDoc->SendScrollToPoint(mID, aScrollType, aX, aY); +} + +int32_t +ProxyAccessible::CaretLineNumber() +{ + int32_t line = -1; + Unused << mDoc->SendCaretOffset(mID, &line); + return line; +} + +int32_t +ProxyAccessible::CaretOffset() +{ + int32_t offset = 0; + Unused << mDoc->SendCaretOffset(mID, &offset); + return offset; +} + +void +ProxyAccessible::SetCaretOffset(int32_t aOffset) +{ + Unused << mDoc->SendSetCaretOffset(mID, aOffset); +} + +int32_t +ProxyAccessible::CharacterCount() +{ + int32_t count = 0; + Unused << mDoc->SendCharacterCount(mID, &count); + return count; +} + +int32_t +ProxyAccessible::SelectionCount() +{ + int32_t count = 0; + Unused << mDoc->SendSelectionCount(mID, &count); + return count; +} + +bool +ProxyAccessible::TextSubstring(int32_t aStartOffset, int32_t aEndOfset, + nsString& aText) const +{ + bool valid; + Unused << mDoc->SendTextSubstring(mID, aStartOffset, aEndOfset, &aText, &valid); + return valid; +} + +void +ProxyAccessible::GetTextAfterOffset(int32_t aOffset, + AccessibleTextBoundary aBoundaryType, + nsString& aText, int32_t* aStartOffset, + int32_t* aEndOffset) +{ + Unused << mDoc->SendGetTextAfterOffset(mID, aOffset, aBoundaryType, + &aText, aStartOffset, aEndOffset); +} + +void +ProxyAccessible::GetTextAtOffset(int32_t aOffset, + AccessibleTextBoundary aBoundaryType, + nsString& aText, int32_t* aStartOffset, + int32_t* aEndOffset) +{ + Unused << mDoc->SendGetTextAtOffset(mID, aOffset, aBoundaryType, + &aText, aStartOffset, aEndOffset); +} + +void +ProxyAccessible::GetTextBeforeOffset(int32_t aOffset, + AccessibleTextBoundary aBoundaryType, + nsString& aText, int32_t* aStartOffset, + int32_t* aEndOffset) +{ + Unused << mDoc->SendGetTextBeforeOffset(mID, aOffset, aBoundaryType, + &aText, aStartOffset, aEndOffset); +} + +char16_t +ProxyAccessible::CharAt(int32_t aOffset) +{ + uint16_t retval = 0; + Unused << mDoc->SendCharAt(mID, aOffset, &retval); + return static_cast<char16_t>(retval); +} + +void +ProxyAccessible::TextAttributes(bool aIncludeDefAttrs, + int32_t aOffset, + nsTArray<Attribute>* aAttributes, + int32_t* aStartOffset, + int32_t* aEndOffset) +{ + Unused << mDoc->SendTextAttributes(mID, aIncludeDefAttrs, aOffset, + aAttributes, aStartOffset, aEndOffset); +} + +void +ProxyAccessible::DefaultTextAttributes(nsTArray<Attribute>* aAttrs) +{ + Unused << mDoc->SendDefaultTextAttributes(mID, aAttrs); +} + +nsIntRect +ProxyAccessible::TextBounds(int32_t aStartOffset, int32_t aEndOffset, + uint32_t aCoordType) +{ + nsIntRect rect; + Unused << + mDoc->SendTextBounds(mID, aStartOffset, aEndOffset, aCoordType, &rect); + return rect; +} + +nsIntRect +ProxyAccessible::CharBounds(int32_t aOffset, uint32_t aCoordType) +{ + nsIntRect rect; + Unused << + mDoc->SendCharBounds(mID, aOffset, aCoordType, &rect); + return rect; +} + +int32_t +ProxyAccessible::OffsetAtPoint(int32_t aX, int32_t aY, uint32_t aCoordType) +{ + int32_t retVal = -1; + Unused << mDoc->SendOffsetAtPoint(mID, aX, aY, aCoordType, &retVal); + return retVal; +} + +bool +ProxyAccessible::SelectionBoundsAt(int32_t aSelectionNum, + nsString& aData, + int32_t* aStartOffset, + int32_t* aEndOffset) +{ + bool retVal = false; + Unused << mDoc->SendSelectionBoundsAt(mID, aSelectionNum, &retVal, &aData, + aStartOffset, aEndOffset); + return retVal; +} + +bool +ProxyAccessible::SetSelectionBoundsAt(int32_t aSelectionNum, + int32_t aStartOffset, + int32_t aEndOffset) +{ + bool retVal = false; + Unused << mDoc->SendSetSelectionBoundsAt(mID, aSelectionNum, aStartOffset, + aEndOffset, &retVal); + return retVal; +} + +bool +ProxyAccessible::AddToSelection(int32_t aStartOffset, + int32_t aEndOffset) +{ + bool retVal = false; + Unused << mDoc->SendAddToSelection(mID, aStartOffset, aEndOffset, &retVal); + return retVal; +} + +bool +ProxyAccessible::RemoveFromSelection(int32_t aSelectionNum) +{ + bool retVal = false; + Unused << mDoc->SendRemoveFromSelection(mID, aSelectionNum, &retVal); + return retVal; +} + +void +ProxyAccessible::ScrollSubstringTo(int32_t aStartOffset, int32_t aEndOffset, + uint32_t aScrollType) +{ + Unused << mDoc->SendScrollSubstringTo(mID, aStartOffset, aEndOffset, aScrollType); +} + +void +ProxyAccessible::ScrollSubstringToPoint(int32_t aStartOffset, + int32_t aEndOffset, + uint32_t aCoordinateType, + int32_t aX, int32_t aY) +{ + Unused << mDoc->SendScrollSubstringToPoint(mID, aStartOffset, aEndOffset, + aCoordinateType, aX, aY); +} + +void +ProxyAccessible::Text(nsString* aText) +{ + Unused << mDoc->SendText(mID, aText); +} + +void +ProxyAccessible::ReplaceText(const nsString& aText) +{ + Unused << mDoc->SendReplaceText(mID, aText); +} + +bool +ProxyAccessible::InsertText(const nsString& aText, int32_t aPosition) +{ + bool valid; + Unused << mDoc->SendInsertText(mID, aText, aPosition, &valid); + return valid; +} + +bool +ProxyAccessible::CopyText(int32_t aStartPos, int32_t aEndPos) +{ + bool valid; + Unused << mDoc->SendCopyText(mID, aStartPos, aEndPos, &valid); + return valid; +} + +bool +ProxyAccessible::CutText(int32_t aStartPos, int32_t aEndPos) +{ + bool valid; + Unused << mDoc->SendCutText(mID, aStartPos, aEndPos, &valid); + return valid; +} + +bool +ProxyAccessible::DeleteText(int32_t aStartPos, int32_t aEndPos) +{ + bool valid; + Unused << mDoc->SendDeleteText(mID, aStartPos, aEndPos, &valid); + return valid; +} + +bool +ProxyAccessible::PasteText(int32_t aPosition) +{ + bool valid; + Unused << mDoc->SendPasteText(mID, aPosition, &valid); + return valid; +} + +nsIntPoint +ProxyAccessible::ImagePosition(uint32_t aCoordType) +{ + nsIntPoint retVal; + Unused << mDoc->SendImagePosition(mID, aCoordType, &retVal); + return retVal; +} + +nsIntSize +ProxyAccessible::ImageSize() +{ + nsIntSize retVal; + Unused << mDoc->SendImageSize(mID, &retVal); + return retVal; +} + +uint32_t +ProxyAccessible::StartOffset(bool* aOk) +{ + uint32_t retVal = 0; + Unused << mDoc->SendStartOffset(mID, &retVal, aOk); + return retVal; +} + +uint32_t +ProxyAccessible::EndOffset(bool* aOk) +{ + uint32_t retVal = 0; + Unused << mDoc->SendEndOffset(mID, &retVal, aOk); + return retVal; +} + +bool +ProxyAccessible::IsLinkValid() +{ + bool retVal = false; + Unused << mDoc->SendIsLinkValid(mID, &retVal); + return retVal; +} + +uint32_t +ProxyAccessible::AnchorCount(bool* aOk) +{ + uint32_t retVal = 0; + Unused << mDoc->SendAnchorCount(mID, &retVal, aOk); + return retVal; +} + +void +ProxyAccessible::AnchorURIAt(uint32_t aIndex, nsCString& aURI, bool* aOk) +{ + Unused << mDoc->SendAnchorURIAt(mID, aIndex, &aURI, aOk); +} + +ProxyAccessible* +ProxyAccessible::AnchorAt(uint32_t aIndex) +{ + uint64_t id = 0; + bool ok = false; + Unused << mDoc->SendAnchorAt(mID, aIndex, &id, &ok); + return ok ? mDoc->GetAccessible(id) : nullptr; +} + +uint32_t +ProxyAccessible::LinkCount() +{ + uint32_t retVal = 0; + Unused << mDoc->SendLinkCount(mID, &retVal); + return retVal; +} + +ProxyAccessible* +ProxyAccessible::LinkAt(const uint32_t& aIndex) +{ + uint64_t linkID = 0; + bool ok = false; + Unused << mDoc->SendLinkAt(mID, aIndex, &linkID, &ok); + return ok ? mDoc->GetAccessible(linkID) : nullptr; +} + +int32_t +ProxyAccessible::LinkIndexOf(ProxyAccessible* aLink) +{ + int32_t retVal = -1; + if (aLink) { + Unused << mDoc->SendLinkIndexOf(mID, aLink->ID(), &retVal); + } + + return retVal; +} + +int32_t +ProxyAccessible::LinkIndexAtOffset(uint32_t aOffset) +{ + int32_t retVal = -1; + Unused << mDoc->SendLinkIndexAtOffset(mID, aOffset, &retVal); + return retVal; +} + +ProxyAccessible* +ProxyAccessible::TableOfACell() +{ + uint64_t tableID = 0; + bool ok = false; + Unused << mDoc->SendTableOfACell(mID, &tableID, &ok); + return ok ? mDoc->GetAccessible(tableID) : nullptr; +} + +uint32_t +ProxyAccessible::ColIdx() +{ + uint32_t index = 0; + Unused << mDoc->SendColIdx(mID, &index); + return index; +} + +uint32_t +ProxyAccessible::RowIdx() +{ + uint32_t index = 0; + Unused << mDoc->SendRowIdx(mID, &index); + return index; +} + +void +ProxyAccessible::GetColRowExtents(uint32_t* aColIdx, uint32_t* aRowIdx, + uint32_t* aColExtent, uint32_t* aRowExtent) +{ + Unused << mDoc->SendGetColRowExtents(mID, aColIdx, aRowIdx, aColExtent, aRowExtent); +} + +void +ProxyAccessible::GetPosition(uint32_t* aColIdx, uint32_t* aRowIdx) +{ + Unused << mDoc->SendGetPosition(mID, aColIdx, aRowIdx); +} + +uint32_t +ProxyAccessible::ColExtent() +{ + uint32_t extent = 0; + Unused << mDoc->SendColExtent(mID, &extent); + return extent; +} + +uint32_t +ProxyAccessible::RowExtent() +{ + uint32_t extent = 0; + Unused << mDoc->SendRowExtent(mID, &extent); + return extent; +} + +void +ProxyAccessible::ColHeaderCells(nsTArray<ProxyAccessible*>* aCells) +{ + nsTArray<uint64_t> targetIDs; + Unused << mDoc->SendColHeaderCells(mID, &targetIDs); + + size_t targetCount = targetIDs.Length(); + for (size_t i = 0; i < targetCount; i++) { + aCells->AppendElement(mDoc->GetAccessible(targetIDs[i])); + } +} + +void +ProxyAccessible::RowHeaderCells(nsTArray<ProxyAccessible*>* aCells) +{ + nsTArray<uint64_t> targetIDs; + Unused << mDoc->SendRowHeaderCells(mID, &targetIDs); + + size_t targetCount = targetIDs.Length(); + for (size_t i = 0; i < targetCount; i++) { + aCells->AppendElement(mDoc->GetAccessible(targetIDs[i])); + } +} + +bool +ProxyAccessible::IsCellSelected() +{ + bool selected = false; + Unused << mDoc->SendIsCellSelected(mID, &selected); + return selected; +} + +ProxyAccessible* +ProxyAccessible::TableCaption() +{ + uint64_t captionID = 0; + bool ok = false; + Unused << mDoc->SendTableCaption(mID, &captionID, &ok); + return ok ? mDoc->GetAccessible(captionID) : nullptr; +} + +void +ProxyAccessible::TableSummary(nsString& aSummary) +{ + Unused << mDoc->SendTableSummary(mID, &aSummary); +} + +uint32_t +ProxyAccessible::TableColumnCount() +{ + uint32_t count = 0; + Unused << mDoc->SendTableColumnCount(mID, &count); + return count; +} + +uint32_t +ProxyAccessible::TableRowCount() +{ + uint32_t count = 0; + Unused << mDoc->SendTableRowCount(mID, &count); + return count; +} + +ProxyAccessible* +ProxyAccessible::TableCellAt(uint32_t aRow, uint32_t aCol) +{ + uint64_t cellID = 0; + bool ok = false; + Unused << mDoc->SendTableCellAt(mID, aRow, aCol, &cellID, &ok); + return ok ? mDoc->GetAccessible(cellID) : nullptr; +} + +int32_t +ProxyAccessible::TableCellIndexAt(uint32_t aRow, uint32_t aCol) +{ + int32_t index = 0; + Unused << mDoc->SendTableCellIndexAt(mID, aRow, aCol, &index); + return index; +} + +int32_t +ProxyAccessible::TableColumnIndexAt(uint32_t aCellIndex) +{ + int32_t index = 0; + Unused << mDoc->SendTableColumnIndexAt(mID, aCellIndex, &index); + return index; +} + +int32_t +ProxyAccessible::TableRowIndexAt(uint32_t aCellIndex) +{ + int32_t index = 0; + Unused << mDoc->SendTableRowIndexAt(mID, aCellIndex, &index); + return index; +} + +void +ProxyAccessible::TableRowAndColumnIndicesAt(uint32_t aCellIndex, + int32_t* aRow, int32_t* aCol) +{ + Unused << mDoc->SendTableRowAndColumnIndicesAt(mID, aCellIndex, aRow, aCol); +} + +uint32_t +ProxyAccessible::TableColumnExtentAt(uint32_t aRow, uint32_t aCol) +{ + uint32_t extent = 0; + Unused << mDoc->SendTableColumnExtentAt(mID, aRow, aCol, &extent); + return extent; +} + +uint32_t +ProxyAccessible::TableRowExtentAt(uint32_t aRow, uint32_t aCol) +{ + uint32_t extent = 0; + Unused << mDoc->SendTableRowExtentAt(mID, aRow, aCol, &extent); + return extent; +} + +void +ProxyAccessible::TableColumnDescription(uint32_t aCol, nsString& aDescription) +{ + Unused << mDoc->SendTableColumnDescription(mID, aCol, &aDescription); +} + +void +ProxyAccessible::TableRowDescription(uint32_t aRow, nsString& aDescription) +{ + Unused << mDoc->SendTableRowDescription(mID, aRow, &aDescription); +} + +bool +ProxyAccessible::TableColumnSelected(uint32_t aCol) +{ + bool selected = false; + Unused << mDoc->SendTableColumnSelected(mID, aCol, &selected); + return selected; +} + +bool +ProxyAccessible::TableRowSelected(uint32_t aRow) +{ + bool selected = false; + Unused << mDoc->SendTableRowSelected(mID, aRow, &selected); + return selected; +} + +bool +ProxyAccessible::TableCellSelected(uint32_t aRow, uint32_t aCol) +{ + bool selected = false; + Unused << mDoc->SendTableCellSelected(mID, aRow, aCol, &selected); + return selected; +} + +uint32_t +ProxyAccessible::TableSelectedCellCount() +{ + uint32_t count = 0; + Unused << mDoc->SendTableSelectedCellCount(mID, &count); + return count; +} + +uint32_t +ProxyAccessible::TableSelectedColumnCount() +{ + uint32_t count = 0; + Unused << mDoc->SendTableSelectedColumnCount(mID, &count); + return count; +} + +uint32_t +ProxyAccessible::TableSelectedRowCount() +{ + uint32_t count = 0; + Unused << mDoc->SendTableSelectedRowCount(mID, &count); + return count; +} + +void +ProxyAccessible::TableSelectedCells(nsTArray<ProxyAccessible*>* aCellIDs) +{ + AutoTArray<uint64_t, 30> cellIDs; + Unused << mDoc->SendTableSelectedCells(mID, &cellIDs); + aCellIDs->SetCapacity(cellIDs.Length()); + for (uint32_t i = 0; i < cellIDs.Length(); ++i) { + aCellIDs->AppendElement(mDoc->GetAccessible(cellIDs[i])); + } +} + +void +ProxyAccessible::TableSelectedCellIndices(nsTArray<uint32_t>* aCellIndices) +{ + Unused << mDoc->SendTableSelectedCellIndices(mID, aCellIndices); +} + +void +ProxyAccessible::TableSelectedColumnIndices(nsTArray<uint32_t>* aColumnIndices) +{ + Unused << mDoc->SendTableSelectedColumnIndices(mID, aColumnIndices); +} + +void +ProxyAccessible::TableSelectedRowIndices(nsTArray<uint32_t>* aRowIndices) +{ + Unused << mDoc->SendTableSelectedRowIndices(mID, aRowIndices); +} + +void +ProxyAccessible::TableSelectColumn(uint32_t aCol) +{ + Unused << mDoc->SendTableSelectColumn(mID, aCol); +} + +void +ProxyAccessible::TableSelectRow(uint32_t aRow) +{ + Unused << mDoc->SendTableSelectRow(mID, aRow); +} + +void +ProxyAccessible::TableUnselectColumn(uint32_t aCol) +{ + Unused << mDoc->SendTableUnselectColumn(mID, aCol); +} + +void +ProxyAccessible::TableUnselectRow(uint32_t aRow) +{ + Unused << mDoc->SendTableUnselectRow(mID, aRow); +} + +bool +ProxyAccessible::TableIsProbablyForLayout() +{ + bool forLayout = false; + Unused << mDoc->SendTableIsProbablyForLayout(mID, &forLayout); + return forLayout; +} + +ProxyAccessible* +ProxyAccessible::AtkTableColumnHeader(int32_t aCol) +{ + uint64_t headerID = 0; + bool ok = false; + Unused << mDoc->SendAtkTableColumnHeader(mID, aCol, &headerID, &ok); + return ok ? mDoc->GetAccessible(headerID) : nullptr; +} + +ProxyAccessible* +ProxyAccessible::AtkTableRowHeader(int32_t aRow) +{ + uint64_t headerID = 0; + bool ok = false; + Unused << mDoc->SendAtkTableRowHeader(mID, aRow, &headerID, &ok); + return ok ? mDoc->GetAccessible(headerID) : nullptr; +} + +void +ProxyAccessible::SelectedItems(nsTArray<ProxyAccessible*>* aSelectedItems) +{ + AutoTArray<uint64_t, 10> itemIDs; + Unused << mDoc->SendSelectedItems(mID, &itemIDs); + aSelectedItems->SetCapacity(itemIDs.Length()); + for (size_t i = 0; i < itemIDs.Length(); ++i) { + aSelectedItems->AppendElement(mDoc->GetAccessible(itemIDs[i])); + } +} + +uint32_t +ProxyAccessible::SelectedItemCount() +{ + uint32_t count = 0; + Unused << mDoc->SendSelectedItemCount(mID, &count); + return count; +} + +ProxyAccessible* +ProxyAccessible::GetSelectedItem(uint32_t aIndex) +{ + uint64_t selectedItemID = 0; + bool ok = false; + Unused << mDoc->SendGetSelectedItem(mID, aIndex, &selectedItemID, &ok); + return ok ? mDoc->GetAccessible(selectedItemID) : nullptr; +} + +bool +ProxyAccessible::IsItemSelected(uint32_t aIndex) +{ + bool selected = false; + Unused << mDoc->SendIsItemSelected(mID, aIndex, &selected); + return selected; +} + +bool +ProxyAccessible::AddItemToSelection(uint32_t aIndex) +{ + bool success = false; + Unused << mDoc->SendAddItemToSelection(mID, aIndex, &success); + return success; +} + +bool +ProxyAccessible::RemoveItemFromSelection(uint32_t aIndex) +{ + bool success = false; + Unused << mDoc->SendRemoveItemFromSelection(mID, aIndex, &success); + return success; +} + +bool +ProxyAccessible::SelectAll() +{ + bool success = false; + Unused << mDoc->SendSelectAll(mID, &success); + return success; +} + +bool +ProxyAccessible::UnselectAll() +{ + bool success = false; + Unused << mDoc->SendUnselectAll(mID, &success); + return success; +} + +void +ProxyAccessible::TakeSelection() +{ + Unused << mDoc->SendTakeSelection(mID); +} + +void +ProxyAccessible::SetSelected(bool aSelect) +{ + Unused << mDoc->SendSetSelected(mID, aSelect); +} + +bool +ProxyAccessible::DoAction(uint8_t aIndex) +{ + bool success = false; + Unused << mDoc->SendDoAction(mID, aIndex, &success); + return success; +} + +uint8_t +ProxyAccessible::ActionCount() +{ + uint8_t count = 0; + Unused << mDoc->SendActionCount(mID, &count); + return count; +} + +void +ProxyAccessible::ActionDescriptionAt(uint8_t aIndex, nsString& aDescription) +{ + Unused << mDoc->SendActionDescriptionAt(mID, aIndex, &aDescription); +} + +void +ProxyAccessible::ActionNameAt(uint8_t aIndex, nsString& aName) +{ + Unused << mDoc->SendActionNameAt(mID, aIndex, &aName); +} + +KeyBinding +ProxyAccessible::AccessKey() +{ + uint32_t key = 0; + uint32_t modifierMask = 0; + Unused << mDoc->SendAccessKey(mID, &key, &modifierMask); + return KeyBinding(key, modifierMask); +} + +KeyBinding +ProxyAccessible::KeyboardShortcut() +{ + uint32_t key = 0; + uint32_t modifierMask = 0; + Unused << mDoc->SendKeyboardShortcut(mID, &key, &modifierMask); + return KeyBinding(key, modifierMask); +} + +void +ProxyAccessible::AtkKeyBinding(nsString& aBinding) +{ + Unused << mDoc->SendAtkKeyBinding(mID, &aBinding); +} + +double +ProxyAccessible::CurValue() +{ + double val = UnspecifiedNaN<double>(); + Unused << mDoc->SendCurValue(mID, &val); + return val; +} + +bool +ProxyAccessible::SetCurValue(double aValue) +{ + bool success = false; + Unused << mDoc->SendSetCurValue(mID, aValue, &success); + return success; +} + +double +ProxyAccessible::MinValue() +{ + double val = UnspecifiedNaN<double>(); + Unused << mDoc->SendMinValue(mID, &val); + return val; +} + +double +ProxyAccessible::MaxValue() +{ + double val = UnspecifiedNaN<double>(); + Unused << mDoc->SendMaxValue(mID, &val); + return val; +} + +double +ProxyAccessible::Step() +{ + double step = UnspecifiedNaN<double>(); + Unused << mDoc->SendStep(mID, &step); + return step; +} + +void +ProxyAccessible::TakeFocus() +{ + Unused << mDoc->SendTakeFocus(mID); +} + +ProxyAccessible* +ProxyAccessible::FocusedChild() +{ + uint64_t childID = 0; + bool ok = false; + Unused << mDoc->SendFocusedChild(mID, &childID, &ok); + return ok ? mDoc->GetAccessible(childID) : nullptr; +} + +ProxyAccessible* +ProxyAccessible::ChildAtPoint(int32_t aX, int32_t aY, + Accessible::EWhichChildAtPoint aWhichChild) +{ + uint64_t childID = 0; + bool ok = false; + Unused << mDoc->SendAccessibleAtPoint(mID, aX, aY, false, + static_cast<uint32_t>(aWhichChild), + &childID, &ok); + return ok ? mDoc->GetAccessible(childID) : nullptr; +} + +nsIntRect +ProxyAccessible::Bounds() +{ + nsIntRect rect; + Unused << mDoc->SendExtents(mID, false, + &(rect.x), &(rect.y), + &(rect.width), &(rect.height)); + return rect; +} + +void +ProxyAccessible::Language(nsString& aLocale) +{ + Unused << mDoc->SendLanguage(mID, &aLocale); +} + +void +ProxyAccessible::DocType(nsString& aType) +{ + Unused << mDoc->SendDocType(mID, &aType); +} + +void +ProxyAccessible::Title(nsString& aTitle) +{ + Unused << mDoc->SendTitle(mID, &aTitle); +} + +void +ProxyAccessible::URL(nsString& aURL) +{ + Unused << mDoc->SendURL(mID, &aURL); +} + +void +ProxyAccessible::MimeType(nsString aMime) +{ + Unused << mDoc->SendMimeType(mID, &aMime); +} + +void +ProxyAccessible::URLDocTypeMimeType(nsString& aURL, nsString& aDocType, + nsString& aMimeType) +{ + Unused << mDoc->SendURLDocTypeMimeType(mID, &aURL, &aDocType, &aMimeType); +} + +ProxyAccessible* +ProxyAccessible::AccessibleAtPoint(int32_t aX, int32_t aY, + bool aNeedsScreenCoords) +{ + uint64_t childID = 0; + bool ok = false; + Unused << + mDoc->SendAccessibleAtPoint(mID, aX, aY, aNeedsScreenCoords, + static_cast<uint32_t>(Accessible::eDirectChild), + &childID, &ok); + return ok ? mDoc->GetAccessible(childID) : nullptr; +} + +void +ProxyAccessible::Extents(bool aNeedsScreenCoords, int32_t* aX, int32_t* aY, + int32_t* aWidth, int32_t* aHeight) +{ + Unused << mDoc->SendExtents(mID, aNeedsScreenCoords, aX, aY, aWidth, aHeight); +} + +void +ProxyAccessible::DOMNodeID(nsString& aID) +{ + Unused << mDoc->SendDOMNodeID(mID, &aID); +} + +} +} diff --git a/accessible/ipc/other/ProxyAccessible.h b/accessible/ipc/other/ProxyAccessible.h new file mode 100644 index 0000000000..25fd71fbf1 --- /dev/null +++ b/accessible/ipc/other/ProxyAccessible.h @@ -0,0 +1,50 @@ +/* -*- 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/. */ + +#ifndef mozilla_a11y_ProxyAccessible_h +#define mozilla_a11y_ProxyAccessible_h + +#include "Accessible.h" +#include "mozilla/a11y/ProxyAccessibleBase.h" +#include "mozilla/a11y/Role.h" +#include "nsIAccessibleText.h" +#include "nsIAccessibleTypes.h" +#include "nsString.h" +#include "nsTArray.h" +#include "nsRect.h" + +namespace mozilla { +namespace a11y { + +class ProxyAccessible : public ProxyAccessibleBase<ProxyAccessible> +{ +public: + + ProxyAccessible(uint64_t aID, ProxyAccessible* aParent, + DocAccessibleParent* aDoc, role aRole, uint32_t aInterfaces) + : ProxyAccessibleBase(aID, aParent, aDoc, aRole, aInterfaces) + + { + MOZ_COUNT_CTOR(ProxyAccessible); + } + + ~ProxyAccessible() + { + MOZ_COUNT_DTOR(ProxyAccessible); + } + +#include "mozilla/a11y/ProxyAccessibleShared.h" + +protected: + explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc) + : ProxyAccessibleBase(aThisAsDoc) + { MOZ_COUNT_CTOR(ProxyAccessible); } +}; + +} +} + +#endif diff --git a/accessible/ipc/other/moz.build b/accessible/ipc/other/moz.build new file mode 100644 index 0000000000..65021145c9 --- /dev/null +++ b/accessible/ipc/other/moz.build @@ -0,0 +1,47 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +# With --disable-accessibility, we need to compile PDocAccessible.ipdl, but +# not the C++. +IPDL_SOURCES += ['PDocAccessible.ipdl'] + +if CONFIG['ACCESSIBILITY']: + EXPORTS.mozilla.a11y += [ + 'DocAccessibleChild.h', + 'ProxyAccessible.h', + ] + + SOURCES += [ + 'DocAccessibleChild.cpp', + 'ProxyAccessible.cpp', + ] + + LOCAL_INCLUDES += [ + '../../base', + '../../generic', + '../../xpcom', + ] + + if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: + LOCAL_INCLUDES += [ + '/accessible/atk', + ] + elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': + LOCAL_INCLUDES += [ + '/accessible/mac', + ] + else: + LOCAL_INCLUDES += [ + '/accessible/other', + ] + +include('/ipc/chromium/chromium-config.mozbuild') + +if CONFIG['GNU_CXX']: + CXXFLAGS += ['-Wno-error=shadow'] + +FINAL_LIBRARY = 'xul' + diff --git a/accessible/ipc/win/COMPtrTypes.cpp b/accessible/ipc/win/COMPtrTypes.cpp new file mode 100644 index 0000000000..857f4235e4 --- /dev/null +++ b/accessible/ipc/win/COMPtrTypes.cpp @@ -0,0 +1,50 @@ +/* -*- 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 "mozilla/a11y/COMPtrTypes.h" + +#include "MainThreadUtils.h" +#include "mozilla/a11y/Accessible.h" +#include "mozilla/Move.h" +#include "mozilla/mscom/MainThreadHandoff.h" +#include "mozilla/RefPtr.h" + +using mozilla::mscom::MainThreadHandoff; +using mozilla::mscom::STAUniquePtr; + +namespace mozilla { +namespace a11y { + +IAccessibleHolder +CreateHolderFromAccessible(Accessible* aAccToWrap) +{ + MOZ_ASSERT(aAccToWrap && NS_IsMainThread()); + if (!aAccToWrap) { + return nullptr; + } + + IAccessible* rawNative = nullptr; + aAccToWrap->GetNativeInterface((void**)&rawNative); + MOZ_ASSERT(rawNative); + if (!rawNative) { + return nullptr; + } + + STAUniquePtr<IAccessible> iaToProxy(rawNative); + + IAccessible* rawIntercepted = nullptr; + HRESULT hr = MainThreadHandoff::WrapInterface(Move(iaToProxy), &rawIntercepted); + MOZ_ASSERT(SUCCEEDED(hr)); + if (FAILED(hr)) { + return nullptr; + } + + IAccessibleHolder::COMPtrType iaIntercepted(rawIntercepted); + return IAccessibleHolder(Move(iaIntercepted)); +} + +} // namespace a11y +} // namespace mozilla diff --git a/accessible/ipc/win/COMPtrTypes.h b/accessible/ipc/win/COMPtrTypes.h new file mode 100644 index 0000000000..122e1ea5ec --- /dev/null +++ b/accessible/ipc/win/COMPtrTypes.h @@ -0,0 +1,27 @@ +/* -*- 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/. */ + +#ifndef mozilla_a11y_COMPtrTypes_h +#define mozilla_a11y_COMPtrTypes_h + +#include "mozilla/mscom/COMPtrHolder.h" + +#include <oleacc.h> + +namespace mozilla { +namespace a11y { + +typedef mozilla::mscom::COMPtrHolder<IAccessible, IID_IAccessible> IAccessibleHolder; + +class Accessible; + +IAccessibleHolder +CreateHolderFromAccessible(Accessible* aAccToWrap); + +} // namespace a11y +} // namespace mozilla + +#endif // mozilla_a11y_COMPtrTypes_h diff --git a/accessible/ipc/win/DocAccessibleChild.cpp b/accessible/ipc/win/DocAccessibleChild.cpp new file mode 100644 index 0000000000..e8b8bebe58 --- /dev/null +++ b/accessible/ipc/win/DocAccessibleChild.cpp @@ -0,0 +1,237 @@ +/* -*- 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 "DocAccessibleChild.h" + +#include "Accessible-inl.h" +#include "mozilla/a11y/PlatformChild.h" +#include "mozilla/ClearOnShutdown.h" +#include "RootAccessible.h" + +namespace mozilla { +namespace a11y { + +static StaticAutoPtr<PlatformChild> sPlatformChild; + +DocAccessibleChild::DocAccessibleChild(DocAccessible* aDoc) + : DocAccessibleChildBase(aDoc) + , mIsRemoteConstructed(false) +{ + MOZ_COUNT_CTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase); + if (!sPlatformChild) { + sPlatformChild = new PlatformChild(); + ClearOnShutdown(&sPlatformChild, ShutdownPhase::Shutdown); + } +} + +DocAccessibleChild::~DocAccessibleChild() +{ + MOZ_COUNT_DTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase); +} + +void +DocAccessibleChild::Shutdown() +{ + if (IsConstructedInParentProcess()) { + DocAccessibleChildBase::Shutdown(); + return; + } + + PushDeferredEvent(MakeUnique<SerializedShutdown>(this)); + DetachDocument(); +} + +bool +DocAccessibleChild::RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy) +{ + MOZ_ASSERT(!mParentProxy && !aParentCOMProxy.IsNull()); + mParentProxy.reset(const_cast<IAccessibleHolder&>(aParentCOMProxy).Release()); + SetConstructedInParentProcess(); + + for (uint32_t i = 0, l = mDeferredEvents.Length(); i < l; ++i) { + mDeferredEvents[i]->Dispatch(); + } + + mDeferredEvents.Clear(); + + return true; +} + +void +DocAccessibleChild::PushDeferredEvent(UniquePtr<DeferredEvent> aEvent) +{ + DocAccessibleChild* topLevelIPCDoc = nullptr; + + if (mDoc && mDoc->IsRoot()) { + topLevelIPCDoc = this; + } else { + auto tabChild = static_cast<dom::TabChild*>(Manager()); + if (!tabChild) { + return; + } + + nsTArray<PDocAccessibleChild*> ipcDocAccs; + tabChild->ManagedPDocAccessibleChild(ipcDocAccs); + + // Look for the top-level DocAccessibleChild - there will only be one + // per TabChild. + for (uint32_t i = 0, l = ipcDocAccs.Length(); i < l; ++i) { + auto ipcDocAcc = static_cast<DocAccessibleChild*>(ipcDocAccs[i]); + if (ipcDocAcc->mDoc && ipcDocAcc->mDoc->IsRoot()) { + topLevelIPCDoc = ipcDocAcc; + break; + } + } + } + + if (topLevelIPCDoc) { + topLevelIPCDoc->mDeferredEvents.AppendElement(Move(aEvent)); + } +} + +bool +DocAccessibleChild::SendEvent(const uint64_t& aID, const uint32_t& aType) +{ + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendEvent(aID, aType); + } + + PushDeferredEvent(MakeUnique<SerializedEvent>(this, aID, aType)); + return false; +} + +void +DocAccessibleChild::MaybeSendShowEvent(ShowEventData& aData, bool aFromUser) +{ + if (IsConstructedInParentProcess()) { + Unused << SendShowEvent(aData, aFromUser); + return; + } + + PushDeferredEvent(MakeUnique<SerializedShow>(this, aData, aFromUser)); +} + +bool +DocAccessibleChild::SendHideEvent(const uint64_t& aRootID, + const bool& aFromUser) +{ + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendHideEvent(aRootID, aFromUser); + } + + PushDeferredEvent(MakeUnique<SerializedHide>(this, aRootID, aFromUser)); + return true; +} + +bool +DocAccessibleChild::SendStateChangeEvent(const uint64_t& aID, + const uint64_t& aState, + const bool& aEnabled) +{ + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendStateChangeEvent(aID, aState, aEnabled); + } + + PushDeferredEvent(MakeUnique<SerializedStateChange>(this, aID, aState, + aEnabled)); + return true; +} + +bool +DocAccessibleChild::SendCaretMoveEvent(const uint64_t& aID, + const int32_t& aOffset) +{ + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendCaretMoveEvent(aID, aOffset); + } + + PushDeferredEvent(MakeUnique<SerializedCaretMove>(this, aID, aOffset)); + return true; +} + +bool +DocAccessibleChild::SendTextChangeEvent(const uint64_t& aID, + const nsString& aStr, + const int32_t& aStart, + const uint32_t& aLen, + const bool& aIsInsert, + const bool& aFromUser) +{ + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendTextChangeEvent(aID, aStr, aStart, + aLen, aIsInsert, aFromUser); + } + + PushDeferredEvent(MakeUnique<SerializedTextChange>(this, aID, aStr, aStart, + aLen, aIsInsert, aFromUser)); + return true; +} + +bool +DocAccessibleChild::SendSelectionEvent(const uint64_t& aID, + const uint64_t& aWidgetID, + const uint32_t& aType) +{ + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendSelectionEvent(aID, aWidgetID, aType); + } + + PushDeferredEvent(MakeUnique<SerializedSelection>(this, aID, + aWidgetID, + aType)); + return true; +} + +bool +DocAccessibleChild::SendRoleChangedEvent(const uint32_t& aRole) +{ + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendRoleChangedEvent(aRole); + } + + PushDeferredEvent(MakeUnique<SerializedRoleChanged>(this, aRole)); + return true; +} + +bool +DocAccessibleChild::ConstructChildDocInParentProcess( + DocAccessibleChild* aNewChildDoc, + uint64_t aUniqueID, uint32_t aMsaaID) +{ + if (IsConstructedInParentProcess()) { + // We may send the constructor immediately + auto tabChild = static_cast<dom::TabChild*>(Manager()); + MOZ_ASSERT(tabChild); + bool result = tabChild->SendPDocAccessibleConstructor(aNewChildDoc, this, + aUniqueID, aMsaaID, + IAccessibleHolder()); + if (result) { + aNewChildDoc->SetConstructedInParentProcess(); + } + return result; + } + + PushDeferredEvent(MakeUnique<SerializedChildDocConstructor>(aNewChildDoc, this, + aUniqueID, aMsaaID)); + return true; +} + +bool +DocAccessibleChild::SendBindChildDoc(DocAccessibleChild* aChildDoc, + const uint64_t& aNewParentID) +{ + if (IsConstructedInParentProcess()) { + return DocAccessibleChildBase::SendBindChildDoc(aChildDoc, aNewParentID); + } + + PushDeferredEvent(MakeUnique<SerializedBindChildDoc>(this, aChildDoc, + aNewParentID)); + return true; +} + +} // namespace a11y +} // namespace mozilla + diff --git a/accessible/ipc/win/DocAccessibleChild.h b/accessible/ipc/win/DocAccessibleChild.h new file mode 100644 index 0000000000..7a3da01725 --- /dev/null +++ b/accessible/ipc/win/DocAccessibleChild.h @@ -0,0 +1,318 @@ +/* -*- 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/. */ + +#ifndef mozilla_a11y_DocAccessibleChild_h +#define mozilla_a11y_DocAccessibleChild_h + +#include "mozilla/a11y/COMPtrTypes.h" +#include "mozilla/a11y/DocAccessibleChildBase.h" +#include "mozilla/dom/TabChild.h" +#include "mozilla/mscom/Ptr.h" + +namespace mozilla { +namespace a11y { + +/* + * These objects handle content side communication for an accessible document, + * and their lifetime is the same as the document they represent. + */ +class DocAccessibleChild : public DocAccessibleChildBase +{ +public: + explicit DocAccessibleChild(DocAccessible* aDoc); + ~DocAccessibleChild(); + + virtual void Shutdown() override; + + virtual bool + RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy) override; + + IAccessible* GetParentIAccessible() const { return mParentProxy.get(); } + + bool SendEvent(const uint64_t& aID, const uint32_t& type); + bool SendHideEvent(const uint64_t& aRootID, const bool& aFromUser); + bool SendStateChangeEvent(const uint64_t& aID, const uint64_t& aState, + const bool& aEnabled); + bool SendCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset); + bool SendTextChangeEvent(const uint64_t& aID, const nsString& aStr, + const int32_t& aStart, const uint32_t& aLen, + const bool& aIsInsert, const bool& aFromUser); + bool SendSelectionEvent(const uint64_t& aID, const uint64_t& aWidgetID, + const uint32_t& aType); + bool SendRoleChangedEvent(const uint32_t& aRole); + + bool ConstructChildDocInParentProcess(DocAccessibleChild* aNewChildDoc, + uint64_t aUniqueID, uint32_t aMsaaID); + + bool SendBindChildDoc(DocAccessibleChild* aChildDoc, + const uint64_t& aNewParentID); + +protected: + virtual void MaybeSendShowEvent(ShowEventData& aData, bool aFromUser) override; + +private: + void RemoveDeferredConstructor(); + + bool IsConstructedInParentProcess() const { return mIsRemoteConstructed; } + void SetConstructedInParentProcess() { mIsRemoteConstructed = true; } + + /** + * DocAccessibleChild should not fire events until it has asynchronously + * received the COM proxy for its parent. OTOH, content a11y may still be + * attempting to fire events during this window of time. If this object does + * not yet have its parent proxy, instead of immediately sending the events to + * our parent, we enqueue them to mDeferredEvents. As soon as + * RecvParentCOMProxy is called, we play back mDeferredEvents. + */ + struct DeferredEvent + { + void Dispatch() + { + Dispatch(mTarget); + } + + virtual ~DeferredEvent() {} + + protected: + explicit DeferredEvent(DocAccessibleChild* aTarget) + : mTarget(aTarget) + {} + + virtual void Dispatch(DocAccessibleChild* aIPCDoc) = 0; + + private: + DocAccessibleChild* mTarget; + }; + + void PushDeferredEvent(UniquePtr<DeferredEvent> aEvent); + + struct SerializedShow final : public DeferredEvent + { + SerializedShow(DocAccessibleChild* aTarget, + ShowEventData& aEventData, bool aFromUser) + : DeferredEvent(aTarget) + , mEventData(aEventData.ID(), aEventData.Idx(), nsTArray<AccessibleData>()) + , mFromUser(aFromUser) + { + // Since IPDL doesn't generate a move constructor for ShowEventData, + // we move NewTree manually (ugh). We still construct with an empty + // NewTree above so that the compiler catches any changes made to the + // ShowEventData structure in IPDL. + mEventData.NewTree() = Move(aEventData.NewTree()); + } + + void Dispatch(DocAccessibleChild* aIPCDoc) override + { + Unused << aIPCDoc->SendShowEvent(mEventData, mFromUser); + } + + ShowEventData mEventData; + bool mFromUser; + }; + + struct SerializedHide final : public DeferredEvent + { + SerializedHide(DocAccessibleChild* aTarget, uint64_t aRootID, bool aFromUser) + : DeferredEvent(aTarget) + , mRootID(aRootID) + , mFromUser(aFromUser) + {} + + void Dispatch(DocAccessibleChild* aIPCDoc) override + { + Unused << aIPCDoc->SendHideEvent(mRootID, mFromUser); + } + + uint64_t mRootID; + bool mFromUser; + }; + + struct SerializedStateChange final : public DeferredEvent + { + SerializedStateChange(DocAccessibleChild* aTarget, uint64_t aID, + uint64_t aState, bool aEnabled) + : DeferredEvent(aTarget) + , mID(aID) + , mState(aState) + , mEnabled(aEnabled) + {} + + void Dispatch(DocAccessibleChild* aIPCDoc) override + { + Unused << aIPCDoc->SendStateChangeEvent(mID, mState, mEnabled); + } + + uint64_t mID; + uint64_t mState; + bool mEnabled; + }; + + struct SerializedCaretMove final : public DeferredEvent + { + SerializedCaretMove(DocAccessibleChild* aTarget, uint64_t aID, + int32_t aOffset) + : DeferredEvent(aTarget) + , mID(aID) + , mOffset(aOffset) + {} + + void Dispatch(DocAccessibleChild* aIPCDoc) override + { + Unused << aIPCDoc->SendCaretMoveEvent(mID, mOffset); + } + + uint64_t mID; + int32_t mOffset; + }; + + struct SerializedTextChange final : public DeferredEvent + { + SerializedTextChange(DocAccessibleChild* aTarget, uint64_t aID, + const nsString& aStr, int32_t aStart, uint32_t aLen, + bool aIsInsert, bool aFromUser) + : DeferredEvent(aTarget) + , mID(aID) + , mStr(aStr) + , mStart(aStart) + , mLen(aLen) + , mIsInsert(aIsInsert) + , mFromUser(aFromUser) + {} + + void Dispatch(DocAccessibleChild* aIPCDoc) override + { + Unused << aIPCDoc->SendTextChangeEvent(mID, mStr, mStart, mLen, mIsInsert, + mFromUser); + } + + uint64_t mID; + nsString mStr; + int32_t mStart; + uint32_t mLen; + bool mIsInsert; + bool mFromUser; + }; + + struct SerializedSelection final : public DeferredEvent + { + SerializedSelection(DocAccessibleChild* aTarget, uint64_t aID, + uint64_t aWidgetID, uint32_t aType) + : DeferredEvent(aTarget) + , mID(aID) + , mWidgetID(aWidgetID) + , mType(aType) + {} + + void Dispatch(DocAccessibleChild* aIPCDoc) override + { + Unused << aIPCDoc->SendSelectionEvent(mID, mWidgetID, mType); + } + + uint64_t mID; + uint64_t mWidgetID; + uint32_t mType; + }; + + struct SerializedRoleChanged final : public DeferredEvent + { + explicit SerializedRoleChanged(DocAccessibleChild* aTarget, uint32_t aRole) + : DeferredEvent(aTarget) + , mRole(aRole) + {} + + void Dispatch(DocAccessibleChild* aIPCDoc) override + { + Unused << aIPCDoc->SendRoleChangedEvent(mRole); + } + + uint32_t mRole; + }; + + struct SerializedEvent final : public DeferredEvent + { + SerializedEvent(DocAccessibleChild* aTarget, uint64_t aID, uint32_t aType) + : DeferredEvent(aTarget) + , mID(aID) + , mType(aType) + {} + + void Dispatch(DocAccessibleChild* aIPCDoc) override + { + Unused << aIPCDoc->SendEvent(mID, mType); + } + + uint64_t mID; + uint32_t mType; + }; + + struct SerializedChildDocConstructor final : public DeferredEvent + { + SerializedChildDocConstructor(DocAccessibleChild* aIPCDoc, + DocAccessibleChild* aParentIPCDoc, + uint64_t aUniqueID, uint32_t aMsaaID) + : DeferredEvent(aParentIPCDoc) + , mIPCDoc(aIPCDoc) + , mUniqueID(aUniqueID) + , mMsaaID(aMsaaID) + {} + + void Dispatch(DocAccessibleChild* aParentIPCDoc) override + { + auto tabChild = static_cast<dom::TabChild*>(aParentIPCDoc->Manager()); + MOZ_ASSERT(tabChild); + Unused << tabChild->SendPDocAccessibleConstructor(mIPCDoc, aParentIPCDoc, + mUniqueID, mMsaaID, + IAccessibleHolder()); + mIPCDoc->SetConstructedInParentProcess(); + } + + DocAccessibleChild* mIPCDoc; + uint64_t mUniqueID; + uint32_t mMsaaID; + }; + + friend struct SerializedChildDocConstructor; + + struct SerializedBindChildDoc final : public DeferredEvent + { + SerializedBindChildDoc(DocAccessibleChild* aParentDoc, + DocAccessibleChild* aChildDoc, uint64_t aNewParentID) + : DeferredEvent(aParentDoc) + , mChildDoc(aChildDoc) + , mNewParentID(aNewParentID) + {} + + void Dispatch(DocAccessibleChild* aParentIPCDoc) override + { + Unused << aParentIPCDoc->SendBindChildDoc(mChildDoc, mNewParentID); + } + + DocAccessibleChild* mChildDoc; + uint64_t mNewParentID; + }; + + struct SerializedShutdown final : public DeferredEvent + { + explicit SerializedShutdown(DocAccessibleChild* aTarget) + : DeferredEvent(aTarget) + { + } + + void Dispatch(DocAccessibleChild* aIPCDoc) override + { + aIPCDoc->Shutdown(); + } + }; + + bool mIsRemoteConstructed; + mscom::ProxyUniquePtr<IAccessible> mParentProxy; + nsTArray<UniquePtr<DeferredEvent>> mDeferredEvents; +}; + +} // namespace a11y +} // namespace mozilla + +#endif // mozilla_a11y_DocAccessibleChild_h diff --git a/accessible/ipc/win/PDocAccessible.ipdl b/accessible/ipc/win/PDocAccessible.ipdl new file mode 100644 index 0000000000..3389abd234 --- /dev/null +++ b/accessible/ipc/win/PDocAccessible.ipdl @@ -0,0 +1,75 @@ +/* -*- 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 protocol PFileDescriptorSet; +include protocol PBrowser; + +using mozilla::a11y::IAccessibleHolder from "mozilla/a11y/IPCTypes.h"; +using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h"; + +namespace mozilla { +namespace a11y { + +struct AccessibleData +{ + uint64_t ID; + int32_t MsaaID; + uint32_t Role; + uint32_t ChildrenCount; + uint32_t Interfaces; +}; + +struct ShowEventData +{ + uint64_t ID; + uint32_t Idx; + AccessibleData[] NewTree; +}; + +struct Attribute +{ + nsCString Name; + nsString Value; +}; + +sync protocol PDocAccessible +{ + manager PBrowser; + +parent: + async Shutdown(); + + /* + * Notify the parent process the document in the child process is firing an + * event. + */ + async Event(uint64_t aID, uint32_t type); + async ShowEvent(ShowEventData data, bool aFromUser); + async HideEvent(uint64_t aRootID, bool aFromUser); + async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled); + async CaretMoveEvent(uint64_t aID, int32_t aOffset); + async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen, + bool aIsInsert, bool aFromUser); + async SelectionEvent(uint64_t aID, uint64_t aWidgetID, uint32_t aType); + async RoleChangedEvent(uint32_t aRole); + + /* + * Tell the parent document to bind the existing document as a new child + * document. + */ + async BindChildDoc(PDocAccessible aChildDoc, uint64_t aID); + + sync GetWindowedPluginIAccessible(WindowsHandle aHwnd) + returns (IAccessibleHolder aPluginCOMProxy); + +child: + async ParentCOMProxy(IAccessibleHolder aParentCOMProxy); + + async __delete__(); +}; + +} +} diff --git a/accessible/ipc/win/PlatformChild.cpp b/accessible/ipc/win/PlatformChild.cpp new file mode 100644 index 0000000000..01434a0811 --- /dev/null +++ b/accessible/ipc/win/PlatformChild.cpp @@ -0,0 +1,62 @@ +/* -*- 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 "mozilla/a11y/PlatformChild.h" +#include "mozilla/mscom/EnsureMTA.h" +#include "mozilla/mscom/InterceptorLog.h" + +#include "Accessible2.h" +#include "Accessible2_2.h" +#include "AccessibleHypertext2.h" +#include "AccessibleTableCell.h" + +#include "AccessibleHypertext2_i.c" + +namespace mozilla { +namespace a11y { + +/** + * Unfortunately the COM interceptor does not intrinsically handle array + * outparams. Instead we manually define the relevant metadata here, and + * register it in a call to mozilla::mscom::RegisterArrayData. + * @see mozilla::mscom::ArrayData + */ +static const mozilla::mscom::ArrayData sPlatformChildArrayData[] = { + {IID_IEnumVARIANT, 3, 1, VT_DISPATCH, IID_IDispatch, 2}, + {IID_IAccessible2, 30, 1, VT_UNKNOWN | VT_BYREF, IID_IAccessibleRelation, 2}, + {IID_IAccessibleRelation, 7, 1, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 2}, + {IID_IAccessible2_2, 48, 2, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 3, + mozilla::mscom::ArrayData::Flag::eAllocatedByServer}, + {IID_IAccessibleTableCell, 4, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1, + mozilla::mscom::ArrayData::Flag::eAllocatedByServer}, + {IID_IAccessibleTableCell, 7, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1, + mozilla::mscom::ArrayData::Flag::eAllocatedByServer}, + {IID_IAccessibleHypertext2, 25, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1, + mozilla::mscom::ArrayData::Flag::eAllocatedByServer} +}; + +// Type libraries are thread-neutral, so we can register those from any +// apartment. OTOH, proxies must be registered from within the apartment where +// we intend to instantiate them. Therefore RegisterProxy() must be called +// via EnsureMTA. +PlatformChild::PlatformChild() + : mAccTypelib(mozilla::mscom::RegisterTypelib(L"oleacc.dll", + mozilla::mscom::RegistrationFlags::eUseSystemDirectory)) + , mMiscTypelib(mozilla::mscom::RegisterTypelib(L"Accessible.tlb")) +{ + mozilla::mscom::InterceptorLog::Init(); + mozilla::mscom::RegisterArrayData(sPlatformChildArrayData); + + UniquePtr<mozilla::mscom::RegisteredProxy> ia2Proxy; + mozilla::mscom::EnsureMTA([&ia2Proxy]() -> void { + ia2Proxy = Move(mozilla::mscom::RegisterProxy(L"ia2marshal.dll")); + }); + mIA2Proxy = Move(ia2Proxy); +} + +} // namespace a11y +} // namespace mozilla + diff --git a/accessible/ipc/win/PlatformChild.h b/accessible/ipc/win/PlatformChild.h new file mode 100644 index 0000000000..49daf161d7 --- /dev/null +++ b/accessible/ipc/win/PlatformChild.h @@ -0,0 +1,35 @@ +/* -*- 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/. */ + +#ifndef mozilla_a11y_PlatformChild_h +#define mozilla_a11y_PlatformChild_h + +#include "mozilla/mscom/Registration.h" + +namespace mozilla { +namespace a11y { + +class PlatformChild +{ +public: + PlatformChild(); + + PlatformChild(PlatformChild&) = delete; + PlatformChild(PlatformChild&&) = delete; + PlatformChild& operator=(PlatformChild&) = delete; + PlatformChild& operator=(PlatformChild&&) = delete; + +private: + UniquePtr<mozilla::mscom::RegisteredProxy> mIA2Proxy; + UniquePtr<mozilla::mscom::RegisteredProxy> mAccTypelib; + UniquePtr<mozilla::mscom::RegisteredProxy> mMiscTypelib; +}; + +} // namespace mozilla +} // namespace a11y + +#endif // mozilla_a11y_PlatformChild_h + diff --git a/accessible/ipc/win/ProxyAccessible.cpp b/accessible/ipc/win/ProxyAccessible.cpp new file mode 100644 index 0000000000..dcdf20ef95 --- /dev/null +++ b/accessible/ipc/win/ProxyAccessible.cpp @@ -0,0 +1,599 @@ +/* -*- 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 "Accessible2.h" +#include "ProxyAccessible.h" +#include "ia2AccessibleValue.h" +#include "mozilla/a11y/DocAccessibleParent.h" +#include "DocAccessible.h" +#include "mozilla/a11y/DocManager.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/TabParent.h" +#include "mozilla/Unused.h" +#include "mozilla/a11y/Platform.h" +#include "RelationType.h" +#include "mozilla/a11y/Role.h" +#include "xpcAccessibleDocument.h" + +#include <comutil.h> + +static const VARIANT kChildIdSelf = {VT_I4}; + +namespace mozilla { +namespace a11y { + +bool +ProxyAccessible::GetCOMInterface(void** aOutAccessible) const +{ + if (!aOutAccessible) { + return false; + } + + if (!mCOMProxy) { + // See if we can lazily obtain a COM proxy + AccessibleWrap* wrap = WrapperFor(this); + bool isDefunct = false; + ProxyAccessible* thisPtr = const_cast<ProxyAccessible*>(this); + // NB: Don't pass CHILDID_SELF here, use the absolute MSAA ID. Otherwise + // GetIAccessibleFor will recurse into this function and we will just + // overflow the stack. + VARIANT realId = {VT_I4}; + realId.ulVal = wrap->GetExistingID(); + thisPtr->mCOMProxy = wrap->GetIAccessibleFor(realId, &isDefunct); + } + + RefPtr<IAccessible> addRefed = mCOMProxy; + addRefed.forget(aOutAccessible); + return !!mCOMProxy; +} + +/** + * Specializations of this template map an IAccessible type to its IID + */ +template<typename Interface> struct InterfaceIID {}; + +template<> +struct InterfaceIID<IAccessibleValue> +{ + static REFIID Value() { return IID_IAccessibleValue; } +}; + +template<> +struct InterfaceIID<IAccessibleText> +{ + static REFIID Value() { return IID_IAccessibleText; } +}; + +/** + * Get the COM proxy for this proxy accessible and QueryInterface it with the + * correct IID + */ +template<typename Interface> +static already_AddRefed<Interface> +QueryInterface(const ProxyAccessible* aProxy) +{ + RefPtr<IAccessible> acc; + if (!aProxy->GetCOMInterface((void**)getter_AddRefs(acc))) { + return nullptr; + } + + RefPtr<Interface> acc2; + if (FAILED(acc->QueryInterface(InterfaceIID<Interface>::Value(), + (void**)getter_AddRefs(acc2)))) { + return nullptr; + } + + return acc2.forget(); +} + +void +ProxyAccessible::Name(nsString& aName) const +{ + aName.Truncate(); + RefPtr<IAccessible> acc; + if (!GetCOMInterface((void**)getter_AddRefs(acc))) { + return; + } + + BSTR result; + HRESULT hr = acc->get_accName(kChildIdSelf, &result); + _bstr_t resultWrap(result, false); + if (FAILED(hr)) { + return; + } + aName = (wchar_t*)resultWrap; +} + +void +ProxyAccessible::Value(nsString& aValue) const +{ + aValue.Truncate(); + RefPtr<IAccessible> acc; + if (!GetCOMInterface((void**)getter_AddRefs(acc))) { + return; + } + + BSTR result; + HRESULT hr = acc->get_accValue(kChildIdSelf, &result); + _bstr_t resultWrap(result, false); + if (FAILED(hr)) { + return; + } + aValue = (wchar_t*)resultWrap; +} + +void +ProxyAccessible::Description(nsString& aDesc) const +{ + aDesc.Truncate(); + RefPtr<IAccessible> acc; + if (!GetCOMInterface((void**)getter_AddRefs(acc))) { + return; + } + + BSTR result; + HRESULT hr = acc->get_accDescription(kChildIdSelf, &result); + _bstr_t resultWrap(result, false); + if (FAILED(hr)) { + return; + } + aDesc = (wchar_t*)resultWrap; +} + +uint64_t +ProxyAccessible::State() const +{ + uint64_t state = 0; + RefPtr<IAccessible> acc; + if (!GetCOMInterface((void**)getter_AddRefs(acc))) { + return state; + } + + VARIANT varState; + HRESULT hr = acc->get_accState(kChildIdSelf, &varState); + if (FAILED(hr)) { + return state; + } + return uint64_t(varState.lVal); +} + +nsIntRect +ProxyAccessible::Bounds() +{ + nsIntRect rect; + + RefPtr<IAccessible> acc; + if (!GetCOMInterface((void**)getter_AddRefs(acc))) { + return rect; + } + + long left; + long top; + long width; + long height; + HRESULT hr = acc->accLocation(&left, &top, &width, &height, kChildIdSelf); + if (FAILED(hr)) { + return rect; + } + rect.x = left; + rect.y = top; + rect.width = width; + rect.height = height; + return rect; +} + +void +ProxyAccessible::Language(nsString& aLocale) +{ + aLocale.Truncate(); + + RefPtr<IAccessible> acc; + if (!GetCOMInterface((void**)getter_AddRefs(acc))) { + return; + } + + RefPtr<IAccessible2> acc2; + if (FAILED(acc->QueryInterface(IID_IAccessible2, (void**)getter_AddRefs(acc2)))) { + return; + } + + IA2Locale locale; + HRESULT hr = acc2->get_locale(&locale); + + _bstr_t langWrap(locale.language, false); + _bstr_t countryWrap(locale.country, false); + _bstr_t variantWrap(locale.variant, false); + + if (FAILED(hr)) { + return; + } + + // The remaining code should essentially be the inverse of the + // ia2Accessible::get_locale conversion to IA2Locale. + + if (!!variantWrap) { + aLocale = (wchar_t*)variantWrap; + return; + } + + if (!!langWrap) { + aLocale = (wchar_t*)langWrap; + if (!!countryWrap) { + aLocale += L"-"; + aLocale += (wchar_t*)countryWrap; + } + } +} + +static bool +IsEscapedChar(const wchar_t c) +{ + return c == L'\\' || c == L':' || c == ',' || c == '=' || c == ';'; +} + +static bool +ConvertBSTRAttributesToArray(const nsAString& aStr, + nsTArray<Attribute>* aAttrs) +{ + if (!aAttrs) { + return false; + } + + enum + { + eName = 0, + eValue = 1, + eNumStates + } state; + nsAutoString tokens[eNumStates]; + auto itr = aStr.BeginReading(), end = aStr.EndReading(); + + state = eName; + while (itr != end) { + switch (*itr) { + case L'\\': + // Skip the backslash so that we're looking at the escaped char + ++itr; + if (itr == end || !IsEscapedChar(*itr)) { + // Invalid state + return false; + } + break; + case L':': + if (state != eName) { + // Bad, should be looking at name + return false; + } + state = eValue; + ++itr; + continue; + case L';': + if (state != eValue) { + // Bad, should be looking at value + return false; + } + state = eName; + aAttrs->AppendElement(Attribute(NS_ConvertUTF16toUTF8(tokens[eName]), + tokens[eValue])); + tokens[eName].Truncate(); + tokens[eValue].Truncate(); + ++itr; + continue; + default: + break; + } + tokens[state] += *itr; + } + return true; +} + +void +ProxyAccessible::Attributes(nsTArray<Attribute>* aAttrs) const +{ + aAttrs->Clear(); + + RefPtr<IAccessible> acc; + if (!GetCOMInterface((void**)getter_AddRefs(acc))) { + return; + } + + RefPtr<IAccessible2> acc2; + if (FAILED(acc->QueryInterface(IID_IAccessible2, (void**)getter_AddRefs(acc2)))) { + return; + } + + BSTR attrs; + HRESULT hr = acc2->get_attributes(&attrs); + _bstr_t attrsWrap(attrs, false); + if (FAILED(hr)) { + return; + } + + ConvertBSTRAttributesToArray(nsDependentString((wchar_t*)attrs, + attrsWrap.length()), + aAttrs); +} + +double +ProxyAccessible::CurValue() +{ + RefPtr<IAccessibleValue> acc = QueryInterface<IAccessibleValue>(this); + if (!acc) { + return UnspecifiedNaN<double>(); + } + + VARIANT currentValue; + HRESULT hr = acc->get_currentValue(¤tValue); + if (FAILED(hr) || currentValue.vt != VT_R8) { + return UnspecifiedNaN<double>(); + } + + return currentValue.dblVal; +} + +bool +ProxyAccessible::SetCurValue(double aValue) +{ + RefPtr<IAccessibleValue> acc = QueryInterface<IAccessibleValue>(this); + if (!acc) { + return false; + } + + VARIANT currentValue; + VariantInit(¤tValue); + currentValue.vt = VT_R8; + currentValue.dblVal = aValue; + HRESULT hr = acc->setCurrentValue(currentValue); + return SUCCEEDED(hr); +} + +double +ProxyAccessible::MinValue() +{ + RefPtr<IAccessibleValue> acc = QueryInterface<IAccessibleValue>(this); + if (!acc) { + return UnspecifiedNaN<double>(); + } + + VARIANT minimumValue; + HRESULT hr = acc->get_minimumValue(&minimumValue); + if (FAILED(hr) || minimumValue.vt != VT_R8) { + return UnspecifiedNaN<double>(); + } + + return minimumValue.dblVal; +} + +double +ProxyAccessible::MaxValue() +{ + RefPtr<IAccessibleValue> acc = QueryInterface<IAccessibleValue>(this); + if (!acc) { + return UnspecifiedNaN<double>(); + } + + VARIANT maximumValue; + HRESULT hr = acc->get_maximumValue(&maximumValue); + if (FAILED(hr) || maximumValue.vt != VT_R8) { + return UnspecifiedNaN<double>(); + } + + return maximumValue.dblVal; +} + +static IA2TextBoundaryType +GetIA2TextBoundary(AccessibleTextBoundary aGeckoBoundaryType) +{ + switch (aGeckoBoundaryType) { + case nsIAccessibleText::BOUNDARY_CHAR: + return IA2_TEXT_BOUNDARY_CHAR; + case nsIAccessibleText::BOUNDARY_WORD_START: + return IA2_TEXT_BOUNDARY_WORD; + case nsIAccessibleText::BOUNDARY_LINE_START: + return IA2_TEXT_BOUNDARY_LINE; + default: + MOZ_RELEASE_ASSERT(false); + } +} + +bool +ProxyAccessible::TextSubstring(int32_t aStartOffset, int32_t aEndOffset, + nsString& aText) const +{ + RefPtr<IAccessibleText> acc = QueryInterface<IAccessibleText>(this); + if (!acc) { + return false; + } + + BSTR result; + HRESULT hr = acc->get_text(static_cast<long>(aStartOffset), + static_cast<long>(aEndOffset), &result); + if (FAILED(hr)) { + return false; + } + + _bstr_t resultWrap(result, false); + aText = (wchar_t*)result; + + return true; +} + +void +ProxyAccessible::GetTextBeforeOffset(int32_t aOffset, + AccessibleTextBoundary aBoundaryType, + nsString& aText, int32_t* aStartOffset, + int32_t* aEndOffset) +{ + RefPtr<IAccessibleText> acc = QueryInterface<IAccessibleText>(this); + if (!acc) { + return; + } + + BSTR result; + long start, end; + HRESULT hr = acc->get_textBeforeOffset(aOffset, + GetIA2TextBoundary(aBoundaryType), + &start, &end, &result); + if (FAILED(hr)) { + return; + } + + _bstr_t resultWrap(result, false); + *aStartOffset = start; + *aEndOffset = end; + aText = (wchar_t*)result; +} + +void +ProxyAccessible::GetTextAfterOffset(int32_t aOffset, + AccessibleTextBoundary aBoundaryType, + nsString& aText, int32_t* aStartOffset, + int32_t* aEndOffset) +{ + RefPtr<IAccessibleText> acc = QueryInterface<IAccessibleText>(this); + if (!acc) { + return; + } + + BSTR result; + long start, end; + HRESULT hr = acc->get_textAfterOffset(aOffset, + GetIA2TextBoundary(aBoundaryType), + &start, &end, &result); + if (FAILED(hr)) { + return; + } + + _bstr_t resultWrap(result, false); + aText = (wchar_t*)result; + *aStartOffset = start; + *aEndOffset = end; +} + +void +ProxyAccessible::GetTextAtOffset(int32_t aOffset, + AccessibleTextBoundary aBoundaryType, + nsString& aText, int32_t* aStartOffset, + int32_t* aEndOffset) +{ + RefPtr<IAccessibleText> acc = QueryInterface<IAccessibleText>(this); + if (!acc) { + return; + } + + BSTR result; + long start, end; + HRESULT hr = acc->get_textAtOffset(aOffset, GetIA2TextBoundary(aBoundaryType), + &start, &end, &result); + if (FAILED(hr)) { + return; + } + + _bstr_t resultWrap(result, false); + aText = (wchar_t*)result; + *aStartOffset = start; + *aEndOffset = end; +} + +bool +ProxyAccessible::AddToSelection(int32_t aStartOffset, int32_t aEndOffset) +{ + RefPtr<IAccessibleText> acc = QueryInterface<IAccessibleText>(this); + if (!acc) { + return false; + } + + return SUCCEEDED(acc->addSelection(static_cast<long>(aStartOffset), + static_cast<long>(aEndOffset))); +} + +bool +ProxyAccessible::RemoveFromSelection(int32_t aSelectionNum) +{ + RefPtr<IAccessibleText> acc = QueryInterface<IAccessibleText>(this); + if (!acc) { + return false; + } + + return SUCCEEDED(acc->removeSelection(static_cast<long>(aSelectionNum))); +} + +int32_t +ProxyAccessible::CaretOffset() +{ + RefPtr<IAccessibleText> acc = QueryInterface<IAccessibleText>(this); + if (!acc) { + return -1; + } + + long offset; + HRESULT hr = acc->get_caretOffset(&offset); + if (FAILED(hr)) { + return -1; + } + + return static_cast<int32_t>(offset); +} + +void +ProxyAccessible::SetCaretOffset(int32_t aOffset) +{ + RefPtr<IAccessibleText> acc = QueryInterface<IAccessibleText>(this); + if (!acc) { + return; + } + + acc->setCaretOffset(static_cast<long>(aOffset)); +} + +/** + * aScrollType should be one of the nsIAccessiblescrollType constants. + */ +void +ProxyAccessible::ScrollSubstringTo(int32_t aStartOffset, int32_t aEndOffset, + uint32_t aScrollType) +{ + RefPtr<IAccessibleText> acc = QueryInterface<IAccessibleText>(this); + if (!acc) { + return; + } + + acc->scrollSubstringTo(static_cast<long>(aStartOffset), + static_cast<long>(aEndOffset), + static_cast<IA2ScrollType>(aScrollType)); +} + +/** + * aCoordinateType is one of the nsIAccessibleCoordinateType constants. + */ +void +ProxyAccessible::ScrollSubstringToPoint(int32_t aStartOffset, int32_t aEndOffset, + uint32_t aCoordinateType, int32_t aX, + int32_t aY) +{ + RefPtr<IAccessibleText> acc = QueryInterface<IAccessibleText>(this); + if (!acc) { + return; + } + + IA2CoordinateType coordType; + if (aCoordinateType == nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE) { + coordType = IA2_COORDTYPE_SCREEN_RELATIVE; + } else if (aCoordinateType == nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE) { + coordType = IA2_COORDTYPE_PARENT_RELATIVE; + } else { + MOZ_RELEASE_ASSERT(false, "unsupported coord type"); + } + + acc->scrollSubstringToPoint(static_cast<long>(aStartOffset), + static_cast<long>(aEndOffset), + coordType, + static_cast<long>(aX), + static_cast<long>(aY)); +} + +} // namespace a11y +} // namespace mozilla diff --git a/accessible/ipc/win/ProxyAccessible.h b/accessible/ipc/win/ProxyAccessible.h new file mode 100644 index 0000000000..c8e5a43b1f --- /dev/null +++ b/accessible/ipc/win/ProxyAccessible.h @@ -0,0 +1,58 @@ +/* -*- 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/. */ + +#ifndef mozilla_a11y_ProxyAccessible_h +#define mozilla_a11y_ProxyAccessible_h + +#include "Accessible.h" +#include "mozilla/a11y/ProxyAccessibleBase.h" +#include "mozilla/a11y/Role.h" +#include "nsIAccessibleText.h" +#include "nsIAccessibleTypes.h" +#include "nsString.h" +#include "nsTArray.h" +#include "nsRect.h" + +#include <oleacc.h> + +namespace mozilla { +namespace a11y { + +class ProxyAccessible : public ProxyAccessibleBase<ProxyAccessible> +{ +public: + ProxyAccessible(uint64_t aID, ProxyAccessible* aParent, + DocAccessibleParent* aDoc, role aRole, uint32_t aInterfaces) + : ProxyAccessibleBase(aID, aParent, aDoc, aRole, aInterfaces) + { + MOZ_COUNT_CTOR(ProxyAccessible); + } + + ~ProxyAccessible() + { + MOZ_COUNT_DTOR(ProxyAccessible); + } + +#include "mozilla/a11y/ProxyAccessibleShared.h" + + bool GetCOMInterface(void** aOutAccessible) const; + +protected: + explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc) + : ProxyAccessibleBase(aThisAsDoc) + { MOZ_COUNT_CTOR(ProxyAccessible); } + + void SetCOMInterface(const RefPtr<IAccessible>& aIAccessible) + { mCOMProxy = aIAccessible; } + +private: + RefPtr<IAccessible> mCOMProxy; +}; + +} +} + +#endif diff --git a/accessible/ipc/win/moz.build b/accessible/ipc/win/moz.build new file mode 100644 index 0000000000..4bbcec417c --- /dev/null +++ b/accessible/ipc/win/moz.build @@ -0,0 +1,39 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +if CONFIG['COMPILE_ENVIRONMENT']: + DIRS += ['typelib'] + +# With --disable-accessibility, we need to compile PDocAccessible.ipdl (which +# also depends on COMPtrTypes.h), but not the C++. +IPDL_SOURCES += ['PDocAccessible.ipdl'] +EXPORTS.mozilla.a11y += ['COMPtrTypes.h'] + +if CONFIG['ACCESSIBILITY']: + EXPORTS.mozilla.a11y += [ + 'DocAccessibleChild.h', + 'PlatformChild.h', + 'ProxyAccessible.h' + ] + + SOURCES += [ + 'COMPtrTypes.cpp', + 'DocAccessibleChild.cpp', + 'PlatformChild.cpp', + 'ProxyAccessible.cpp', + ] + + LOCAL_INCLUDES += [ + '/accessible/base', + '/accessible/generic', + '/accessible/windows/ia2', + '/accessible/windows/msaa', + '/accessible/xpcom', + ] + +include('/ipc/chromium/chromium-config.mozbuild') + +FINAL_LIBRARY = 'xul' diff --git a/accessible/ipc/win/typelib/Accessible.idl b/accessible/ipc/win/typelib/Accessible.idl new file mode 100644 index 0000000000..82ddcf5065 --- /dev/null +++ b/accessible/ipc/win/typelib/Accessible.idl @@ -0,0 +1,16 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=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/. */ + +import "oaidl.idl"; +import "servprov.idl"; + +[uuid(b4d37cda-0dac-45e6-b613-158a5eb94293)] +library Accessible +{ + interface IEnumVARIANT; + interface IServiceProvider; +}; + diff --git a/accessible/ipc/win/typelib/Makefile.in b/accessible/ipc/win/typelib/Makefile.in new file mode 100644 index 0000000000..78e0cea299 --- /dev/null +++ b/accessible/ipc/win/typelib/Makefile.in @@ -0,0 +1,31 @@ +# 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/. + +GARBAGE += $(MIDL_GENERATED_FILES) done_gen dlldata.c + +MIDL_GENERATED_FILES = \ + Accessible.h \ + Accessible_i.c \ + Accessible_p.c \ + Accessible.tlb \ + $(NULL) + +$(MIDL_GENERATED_FILES): done_gen + +done_gen: Accessible.idl + $(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/Accessible.idl + touch $@ + +export:: done_gen + +midl_exports := \ + Accessible.tlb \ + $(NULL) + +INSTALL_TARGETS += midl_exports +midl_exports_FILES := $(midl_exports) +midl_exports_DEST = $(DIST)/bin +midl_exports_TARGET := export + +include $(topsrcdir)/config/rules.mk diff --git a/accessible/ipc/win/typelib/moz.build b/accessible/ipc/win/typelib/moz.build new file mode 100644 index 0000000000..3bc45a136d --- /dev/null +++ b/accessible/ipc/win/typelib/moz.build @@ -0,0 +1,13 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +FINAL_TARGET_FILES += [ + '!Accessible.tlb', +] + +GENERATED_FILES += [ + 'Accessible.tlb', +] |