зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1268544: Refactor ProxyAccessible and dependencies; r=tbsaunde
MozReview-Commit-ID: EHV0JR6NmKf --HG-- rename : accessible/ipc/ProxyAccessible.cpp => accessible/ipc/ProxyAccessibleBase.cpp rename : accessible/ipc/ProxyAccessible.h => accessible/ipc/ProxyAccessibleBase.h rename : accessible/ipc/ProxyAccessible.cpp => accessible/ipc/other/ProxyAccessible.cpp rename : accessible/ipc/ProxyAccessible.h => accessible/ipc/other/ProxyAccessible.h rename : accessible/ipc/ProxyAccessible.cpp => accessible/ipc/win/ProxyAccessible.cpp rename : accessible/ipc/ProxyAccessible.h => accessible/ipc/win/ProxyAccessible.h
This commit is contained in:
Родитель
1d9ba42f65
Коммит
1597663492
|
@ -0,0 +1,159 @@
|
|||
/* -*- 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* aParent)
|
||||
{
|
||||
if (aParent) {
|
||||
MOZ_ASSERT(mChildren.IsEmpty());
|
||||
mChildren.AppendElement(aParent);
|
||||
mOuterDoc = true;
|
||||
} else {
|
||||
MOZ_ASSERT(mChildren.Length() == 1);
|
||||
mChildren.Clear();
|
||||
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
|
|
@ -0,0 +1,190 @@
|
|||
/* -*- 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(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)
|
||||
{
|
||||
}
|
||||
|
||||
~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*);
|
||||
|
||||
/**
|
||||
* 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; }
|
||||
|
||||
|
||||
protected:
|
||||
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)
|
||||
{ MOZ_COUNT_CTOR(ProxyAccessibleBase); }
|
||||
|
||||
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
|
|
@ -38,13 +38,13 @@ if CONFIG['ACCESSIBILITY']:
|
|||
EXPORTS.mozilla.a11y += [
|
||||
'DocAccessibleChildBase.h',
|
||||
'DocAccessibleParent.h',
|
||||
'ProxyAccessible.h'
|
||||
'ProxyAccessibleBase.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'DocAccessibleChildBase.cpp',
|
||||
'DocAccessibleParent.cpp',
|
||||
'ProxyAccessible.cpp'
|
||||
'ProxyAccessibleBase.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ProxyAccessible.h"
|
||||
#include "DocAccessibleParent.h"
|
||||
#include "mozilla/a11y/DocAccessibleParent.h"
|
||||
#include "DocAccessible.h"
|
||||
#include "mozilla/a11y/DocManager.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
@ -19,69 +19,6 @@
|
|||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
void
|
||||
ProxyAccessible::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(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(this);
|
||||
mDoc->RemoveAccessible(this);
|
||||
}
|
||||
|
||||
void
|
||||
ProxyAccessible::SetChildDoc(DocAccessibleParent* aParent)
|
||||
{
|
||||
if (aParent) {
|
||||
MOZ_ASSERT(mChildren.IsEmpty());
|
||||
mChildren.AppendElement(aParent);
|
||||
mOuterDoc = true;
|
||||
} else {
|
||||
MOZ_ASSERT(mChildren.Length() == 1);
|
||||
mChildren.Clear();
|
||||
mOuterDoc = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ProxyAccessible::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;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
ProxyAccessible::State() const
|
||||
{
|
||||
|
@ -1032,55 +969,6 @@ ProxyAccessible::TakeFocus()
|
|||
Unused << mDoc->SendTakeFocus(mID);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ProxyAccessible::EmbeddedChildCount() const
|
||||
{
|
||||
size_t count = 0, kids = mChildren.Length();
|
||||
for (size_t i = 0; i < kids; i++) {
|
||||
if (mChildren[i]->IsEmbeddedObject()) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int32_t
|
||||
ProxyAccessible::IndexOfEmbeddedChild(const ProxyAccessible* 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;
|
||||
}
|
||||
|
||||
ProxyAccessible*
|
||||
ProxyAccessible::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;
|
||||
}
|
||||
|
||||
ProxyAccessible*
|
||||
ProxyAccessible::FocusedChild()
|
||||
{
|
||||
|
@ -1175,18 +1063,5 @@ ProxyAccessible::DOMNodeID(nsString& aID)
|
|||
Unused << mDoc->SendDOMNodeID(mID, &aID);
|
||||
}
|
||||
|
||||
Accessible*
|
||||
ProxyAccessible::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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,115 +7,33 @@
|
|||
#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 "Accessible.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsRect.h"
|
||||
#include "Accessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
class Accessible;
|
||||
class Attribute;
|
||||
class DocAccessibleParent;
|
||||
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,
|
||||
};
|
||||
|
||||
class ProxyAccessible
|
||||
class ProxyAccessible : public ProxyAccessibleBase<ProxyAccessible>
|
||||
{
|
||||
public:
|
||||
|
||||
ProxyAccessible(uint64_t aID, ProxyAccessible* 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)
|
||||
DocAccessibleParent* aDoc, role aRole, uint32_t aInterfaces)
|
||||
: ProxyAccessibleBase(aID, aParent, aDoc, aRole, aInterfaces)
|
||||
|
||||
{
|
||||
MOZ_COUNT_CTOR(ProxyAccessible);
|
||||
}
|
||||
|
||||
~ProxyAccessible()
|
||||
{
|
||||
MOZ_COUNT_DTOR(ProxyAccessible);
|
||||
MOZ_ASSERT(!mWrapper);
|
||||
}
|
||||
|
||||
void AddChildAt(uint32_t aIdx, ProxyAccessible* aChild)
|
||||
{ mChildren.InsertElementAt(aIdx, aChild); }
|
||||
|
||||
uint32_t ChildrenCount() const { return mChildren.Length(); }
|
||||
ProxyAccessible* ChildAt(uint32_t aIdx) const { return mChildren[aIdx]; }
|
||||
ProxyAccessible* FirstChild() const
|
||||
{ return mChildren.Length() ? mChildren[0] : nullptr; }
|
||||
ProxyAccessible* LastChild() const
|
||||
{ return mChildren.Length() ? mChildren[mChildren.Length() - 1] : nullptr; }
|
||||
ProxyAccessible* PrevSibling() const
|
||||
{
|
||||
size_t idx = IndexInParent();
|
||||
return idx > 0 ? Parent()->mChildren[idx - 1] : nullptr;
|
||||
}
|
||||
ProxyAccessible* 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(this); }
|
||||
uint32_t EmbeddedChildCount() const;
|
||||
int32_t IndexOfEmbeddedChild(const ProxyAccessible*);
|
||||
ProxyAccessible* EmbeddedChildAt(size_t aChildIdx);
|
||||
bool MustPruneChildren() const;
|
||||
|
||||
void Shutdown();
|
||||
|
||||
void SetChildDoc(DocAccessibleParent*);
|
||||
|
||||
/**
|
||||
* Remove The given child.
|
||||
*/
|
||||
void RemoveChild(ProxyAccessible* aChild)
|
||||
{ mChildren.RemoveElement(aChild); }
|
||||
|
||||
/**
|
||||
* Return the proxy for the parent of the wrapped accessible.
|
||||
*/
|
||||
ProxyAccessible* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -396,56 +314,10 @@ public:
|
|||
*/
|
||||
void DOMNodeID(nsString& aID);
|
||||
|
||||
/**
|
||||
* 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; }
|
||||
|
||||
protected:
|
||||
explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc) :
|
||||
mParent(nullptr), mDoc(aThisAsDoc), mWrapper(0), mID(0),
|
||||
mRole(roles::DOCUMENT), mOuterDoc(false), mIsDoc(true), mHasValue(false),
|
||||
mIsHyperLink(false), mIsHyperText(false)
|
||||
explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc)
|
||||
: ProxyAccessibleBase(aThisAsDoc)
|
||||
{ MOZ_COUNT_CTOR(ProxyAccessible); }
|
||||
|
||||
protected:
|
||||
ProxyAccessible* mParent;
|
||||
|
||||
private:
|
||||
nsTArray<ProxyAccessible*> 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;
|
||||
};
|
||||
|
||||
}
|
|
@ -11,12 +11,12 @@ IPDL_SOURCES += ['PDocAccessible.ipdl']
|
|||
if CONFIG['ACCESSIBILITY']:
|
||||
EXPORTS.mozilla.a11y += [
|
||||
'DocAccessibleChild.h',
|
||||
'ProxyAccessible.h'
|
||||
'ProxyAccessible.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'DocAccessibleChild.cpp',
|
||||
'ProxyAccessible.cpp'
|
||||
'ProxyAccessible.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
|
|
|
@ -0,0 +1,280 @@
|
|||
/* -*- 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 "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>
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
bool
|
||||
ProxyAccessible::GetCOMInterface(void** aOutAccessible) const
|
||||
{
|
||||
if (!aOutAccessible) {
|
||||
return false;
|
||||
}
|
||||
RefPtr<IAccessible> addRefed = mCOMProxy;
|
||||
addRefed.forget(aOutAccessible);
|
||||
return !!mCOMProxy;
|
||||
}
|
||||
|
||||
void
|
||||
ProxyAccessible::Name(nsString& aName) const
|
||||
{
|
||||
aName.Truncate();
|
||||
RefPtr<IAccessible> acc;
|
||||
if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
|
||||
return;
|
||||
}
|
||||
|
||||
VARIANT id;
|
||||
id.vt = VT_I4;
|
||||
id.lVal = CHILDID_SELF;
|
||||
BSTR result;
|
||||
HRESULT hr = acc->get_accName(id, &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;
|
||||
}
|
||||
|
||||
VARIANT id;
|
||||
id.vt = VT_I4;
|
||||
id.lVal = CHILDID_SELF;
|
||||
BSTR result;
|
||||
HRESULT hr = acc->get_accValue(id, &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;
|
||||
}
|
||||
|
||||
VARIANT id;
|
||||
id.vt = VT_I4;
|
||||
id.lVal = CHILDID_SELF;
|
||||
BSTR result;
|
||||
HRESULT hr = acc->get_accDescription(id, &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 id;
|
||||
id.vt = VT_I4;
|
||||
id.lVal = CHILDID_SELF;
|
||||
VARIANT varState;
|
||||
HRESULT hr = acc->get_accState(id, &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;
|
||||
VARIANT id;
|
||||
id.vt = VT_I4;
|
||||
id.lVal = CHILDID_SELF;
|
||||
HRESULT hr = acc->accLocation(&left, &top, &width, &height, id);
|
||||
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);
|
||||
}
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,88 @@
|
|||
/* -*- 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,
|
||||
const RefPtr<IAccessible>& aIAccessible)
|
||||
: ProxyAccessibleBase(aID, aParent, aDoc, aRole, aInterfaces)
|
||||
, mCOMProxy(aIAccessible)
|
||||
|
||||
{
|
||||
MOZ_COUNT_CTOR(ProxyAccessible);
|
||||
}
|
||||
|
||||
~ProxyAccessible()
|
||||
{
|
||||
MOZ_COUNT_DTOR(ProxyAccessible);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the states for the proxied accessible.
|
||||
*/
|
||||
uint64_t State() 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 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;
|
||||
|
||||
nsIntRect Bounds();
|
||||
|
||||
void Language(nsString& aLocale);
|
||||
|
||||
bool GetCOMInterface(void** aOutAccessible) const;
|
||||
|
||||
protected:
|
||||
explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc)
|
||||
: ProxyAccessibleBase(aThisAsDoc)
|
||||
{ MOZ_COUNT_CTOR(ProxyAccessibleBase); }
|
||||
|
||||
void SetCOMInterface(const RefPtr<IAccessible>& aIAccessible)
|
||||
{ mCOMProxy = aIAccessible; }
|
||||
|
||||
private:
|
||||
RefPtr<IAccessible> mCOMProxy;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -12,11 +12,13 @@ if CONFIG['ACCESSIBILITY']:
|
|||
EXPORTS.mozilla.a11y += [
|
||||
'COMPtrTypes.h',
|
||||
'DocAccessibleChild.h',
|
||||
'ProxyAccessible.h'
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'COMPtrTypes.cpp',
|
||||
'DocAccessibleChild.cpp',
|
||||
'ProxyAccessible.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace a11y {
|
|||
|
||||
class ProxyAccessibleWrap : public AccessibleWrap
|
||||
{
|
||||
public:
|
||||
public:
|
||||
ProxyAccessibleWrap(ProxyAccessible* aProxy) :
|
||||
AccessibleWrap(nullptr, nullptr)
|
||||
{
|
||||
|
@ -28,6 +28,11 @@ class ProxyAccessibleWrap : public AccessibleWrap
|
|||
mBits.proxy = nullptr;
|
||||
mStateFlags |= eIsDefunct;
|
||||
}
|
||||
|
||||
virtual void GetNativeInterface(void** aOutAccessible) override
|
||||
{
|
||||
mBits.proxy->GetCOMInterface(aOutAccessible);
|
||||
}
|
||||
};
|
||||
|
||||
class HyperTextProxyAccessibleWrap : public HyperTextAccessibleWrap
|
||||
|
@ -43,7 +48,12 @@ public:
|
|||
virtual void Shutdown() override
|
||||
{
|
||||
mBits.proxy = nullptr;
|
||||
mStateFlags |= eIsDefunct;
|
||||
mStateFlags |= eIsDefunct;
|
||||
}
|
||||
|
||||
virtual void GetNativeInterface(void** aOutAccessible) override
|
||||
{
|
||||
mBits.proxy->GetCOMInterface(aOutAccessible);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ private:
|
|||
friend class DocManager;
|
||||
friend class DocAccessible;
|
||||
friend class ProxyAccessible;
|
||||
friend class ProxyAccessibleBase<ProxyAccessible>;
|
||||
|
||||
xpcAccessibleDocument(const xpcAccessibleDocument&) = delete;
|
||||
xpcAccessibleDocument& operator =(const xpcAccessibleDocument&) = delete;
|
||||
|
|
Загрузка…
Ссылка в новой задаче