mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1297549: Part 1 - Use chrome-generated MSAA IDs in content; r=tbsaunde
MozReview-Commit-ID: 7YIx7f6KEOs
This commit is contained in:
parent
c67efa31d7
commit
6eb5eabb31
@ -82,6 +82,29 @@ DocAccessibleChildBase::SerializeTree(Accessible* aRoot,
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
/* static */ void
|
||||
DocAccessibleChildBase::SetMsaaIds(Accessible* aRoot,
|
||||
uint32_t& aMsaaIdIndex,
|
||||
const nsTArray<MsaaMapping>& aNewMsaaIds)
|
||||
{
|
||||
const MsaaMapping& mapping = aNewMsaaIds[aMsaaIdIndex];
|
||||
#if defined(DEBUG)
|
||||
uint64_t id = reinterpret_cast<uint64_t>(aRoot->UniqueID());
|
||||
MOZ_ASSERT(mapping.ID() == id);
|
||||
#endif // defined(DEBUG)
|
||||
static_cast<AccessibleWrap*>(aRoot)->SetID(mapping.MsaaID());
|
||||
++aMsaaIdIndex;
|
||||
if (aRoot->IsOuterDoc()) {
|
||||
// This needs to match the tree traversal in SerializeTree
|
||||
return;
|
||||
}
|
||||
for (uint32_t i = 0, n = aRoot->ChildCount(); i < n; ++i) {
|
||||
SetMsaaIds(aRoot->GetChildAt(i), aMsaaIdIndex, aNewMsaaIds);
|
||||
}
|
||||
}
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
void
|
||||
DocAccessibleChildBase::ShowEvent(AccShowEvent* aShowEvent)
|
||||
{
|
||||
@ -91,7 +114,22 @@ DocAccessibleChildBase::ShowEvent(AccShowEvent* aShowEvent)
|
||||
nsTArray<AccessibleData> shownTree;
|
||||
ShowEventData data(parentID, idxInParent, shownTree);
|
||||
SerializeTree(aShowEvent->GetAccessible(), data.NewTree());
|
||||
#if defined(XP_WIN)
|
||||
nsTArray<MsaaMapping> newMsaaIds;
|
||||
SendShowEventInfo(data, &newMsaaIds);
|
||||
// newMsaaIds could be empty if something went wrong in SendShowEvent()
|
||||
if (!newMsaaIds.IsEmpty()) {
|
||||
uint32_t index = 0;
|
||||
SetMsaaIds(aShowEvent->GetAccessible(), index, newMsaaIds);
|
||||
}
|
||||
// NB: On Windows, SendShowEvent attaches the subtree and generates new IDs,
|
||||
// but does *NOT* fire the native event. We need to do that after
|
||||
// we've called SetMsaaIds.
|
||||
SendEvent(reinterpret_cast<uint64_t>(aShowEvent->GetAccessible()->UniqueID()),
|
||||
nsIAccessibleEvent::EVENT_SHOW);
|
||||
#else
|
||||
SendShowEvent(data, aShowEvent->IsFromUserInput());
|
||||
#endif // defined(XP_WIN)
|
||||
}
|
||||
|
||||
} // namespace a11y
|
||||
|
@ -60,6 +60,10 @@ public:
|
||||
protected:
|
||||
static uint32_t InterfacesFor(Accessible* aAcc);
|
||||
static void SerializeTree(Accessible* aRoot, nsTArray<AccessibleData>& aTree);
|
||||
#if defined(XP_WIN)
|
||||
static void SetMsaaIds(Accessible* aRoot, uint32_t& aMsaaIdIndex,
|
||||
const nsTArray<MsaaMapping>& aNewMsaaIds);
|
||||
#endif
|
||||
|
||||
DocAccessible* mDoc;
|
||||
};
|
||||
|
@ -16,8 +16,13 @@ namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
bool
|
||||
#if defined(XP_WIN)
|
||||
DocAccessibleParent::RecvShowEventInfo(const ShowEventData& aData,
|
||||
nsTArray<MsaaMapping>* aNewMsaaIds)
|
||||
#else
|
||||
DocAccessibleParent::RecvShowEvent(const ShowEventData& aData,
|
||||
const bool& aFromUser)
|
||||
#endif // defined(XP_WIN)
|
||||
{
|
||||
if (mShutdown)
|
||||
return true;
|
||||
@ -44,7 +49,13 @@ DocAccessibleParent::RecvShowEvent(const ShowEventData& aData,
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
aNewMsaaIds->SetCapacity(aData.NewTree().Length());
|
||||
uint32_t consumed = AddSubtree(parent, aData.NewTree(), 0, newChildIdx,
|
||||
aNewMsaaIds);
|
||||
#else
|
||||
uint32_t consumed = AddSubtree(parent, aData.NewTree(), 0, newChildIdx);
|
||||
#endif
|
||||
MOZ_ASSERT(consumed == aData.NewTree().Length());
|
||||
|
||||
// XXX This shouldn't happen, but if we failed to add children then the below
|
||||
@ -62,6 +73,9 @@ DocAccessibleParent::RecvShowEvent(const ShowEventData& aData,
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
|
||||
|
||||
// NB: On Windows we dispatch the native event via a subsequent call to
|
||||
// RecvEvent().
|
||||
#if !defined(XP_WIN)
|
||||
ProxyAccessible* target = parent->ChildAt(newChildIdx);
|
||||
ProxyShowHideEvent(target, parent, true, aFromUser);
|
||||
|
||||
@ -76,6 +90,7 @@ DocAccessibleParent::RecvShowEvent(const ShowEventData& aData,
|
||||
RefPtr<xpcAccEvent> event = new xpcAccEvent(type, xpcAcc, doc, node,
|
||||
aFromUser);
|
||||
nsCoreUtils::DispatchAccEvent(Move(event));
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -83,7 +98,11 @@ DocAccessibleParent::RecvShowEvent(const ShowEventData& aData,
|
||||
uint32_t
|
||||
DocAccessibleParent::AddSubtree(ProxyAccessible* aParent,
|
||||
const nsTArray<a11y::AccessibleData>& aNewTree,
|
||||
uint32_t aIdx, uint32_t aIdxInParent)
|
||||
uint32_t aIdx, uint32_t aIdxInParent
|
||||
#if defined(XP_WIN)
|
||||
, nsTArray<MsaaMapping>* aNewMsaaIds
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (aNewTree.Length() <= aIdx) {
|
||||
NS_ERROR("bad index in serialized tree!");
|
||||
@ -124,10 +143,22 @@ DocAccessibleParent::AddSubtree(ProxyAccessible* aParent,
|
||||
mAccessibles.PutEntry(newChild.ID())->mProxy = newProxy;
|
||||
ProxyCreated(newProxy, newChild.Interfaces());
|
||||
|
||||
#if defined(XP_WIN)
|
||||
Accessible* idForAcc = WrapperFor(newProxy);
|
||||
MOZ_ASSERT(idForAcc);
|
||||
uint32_t newMsaaId = AccessibleWrap::GetChildIDFor(idForAcc);
|
||||
MOZ_ASSERT(newMsaaId);
|
||||
aNewMsaaIds->AppendElement(MsaaMapping(newChild.ID(), newMsaaId));
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
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);
|
||||
uint32_t consumed = AddSubtree(newProxy, aNewTree, aIdx + accessibles, i
|
||||
#if defined(XP_WIN)
|
||||
, aNewMsaaIds
|
||||
#endif
|
||||
);
|
||||
if (!consumed)
|
||||
return 0;
|
||||
|
||||
@ -476,7 +507,8 @@ DocAccessibleParent::GetXPCAccessible(ProxyAccessible* aProxy)
|
||||
*/
|
||||
bool
|
||||
DocAccessibleParent::RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
|
||||
IAccessibleHolder* aParentCOMProxy)
|
||||
IAccessibleHolder* aParentCOMProxy,
|
||||
uint32_t* aMsaaID)
|
||||
{
|
||||
RefPtr<IAccessible> ptr(aCOMProxy.Get());
|
||||
SetCOMInterface(ptr);
|
||||
@ -488,6 +520,8 @@ DocAccessibleParent::RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
|
||||
}
|
||||
|
||||
aParentCOMProxy->Set(IAccessibleHolder::COMPtrType(rawNative));
|
||||
Accessible* wrapper = WrapperFor(this);
|
||||
*aMsaaID = AccessibleWrap::GetChildIDFor(wrapper);
|
||||
return true;
|
||||
}
|
||||
#endif // defined(XP_WIN)
|
||||
|
@ -50,8 +50,13 @@ public:
|
||||
virtual bool RecvEvent(const uint64_t& aID, const uint32_t& aType)
|
||||
override;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
virtual bool RecvShowEventInfo(const ShowEventData& aData,
|
||||
nsTArray<MsaaMapping>* aNewMsaaIds) override;
|
||||
#else
|
||||
virtual bool RecvShowEvent(const ShowEventData& aData, const bool& aFromUser)
|
||||
override;
|
||||
#endif // defined(XP_WIN)
|
||||
virtual bool RecvHideEvent(const uint64_t& aRootID, const bool& aFromUser)
|
||||
override;
|
||||
virtual bool RecvStateChangeEvent(const uint64_t& aID,
|
||||
@ -144,7 +149,8 @@ public:
|
||||
|
||||
#if defined(XP_WIN)
|
||||
virtual bool RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
|
||||
IAccessibleHolder* aParentCOMProxy) override;
|
||||
IAccessibleHolder* aParentCOMProxy,
|
||||
uint32_t* aMsaaID) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
@ -174,7 +180,11 @@ private:
|
||||
|
||||
uint32_t AddSubtree(ProxyAccessible* aParent,
|
||||
const nsTArray<AccessibleData>& aNewTree, uint32_t aIdx,
|
||||
uint32_t aIdxInParent);
|
||||
uint32_t aIdxInParent
|
||||
#if defined(XP_WIN)
|
||||
, nsTArray<MsaaMapping>* aNewMsaaIds
|
||||
#endif // defined(XP_WIN)
|
||||
);
|
||||
MOZ_MUST_USE bool CheckDocTree() const;
|
||||
xpcAccessibleGeneric* GetXPCAccessible(ProxyAccessible* aProxy);
|
||||
|
||||
|
@ -34,8 +34,10 @@ void
|
||||
DocAccessibleChild::SendCOMProxy(const IAccessibleHolder& aProxy)
|
||||
{
|
||||
IAccessibleHolder parentProxy;
|
||||
PDocAccessibleChild::SendCOMProxy(aProxy, &parentProxy);
|
||||
uint32_t msaaID = AccessibleWrap::kNoID;
|
||||
PDocAccessibleChild::SendCOMProxy(aProxy, &parentProxy, &msaaID);
|
||||
mParentProxy.reset(parentProxy.Release());
|
||||
mDoc->SetID(msaaID);
|
||||
}
|
||||
|
||||
} // namespace a11y
|
||||
|
@ -27,6 +27,12 @@ struct ShowEventData
|
||||
AccessibleData[] NewTree;
|
||||
};
|
||||
|
||||
struct MsaaMapping
|
||||
{
|
||||
uint64_t ID;
|
||||
uint32_t MsaaID;
|
||||
};
|
||||
|
||||
struct Attribute
|
||||
{
|
||||
nsCString Name;
|
||||
@ -45,7 +51,7 @@ parent:
|
||||
* event.
|
||||
*/
|
||||
async Event(uint64_t aID, uint32_t type);
|
||||
async ShowEvent(ShowEventData data, bool aFromuser);
|
||||
sync ShowEventInfo(ShowEventData data) returns (MsaaMapping[] aNewMsaaIds);
|
||||
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);
|
||||
@ -63,7 +69,7 @@ parent:
|
||||
// For now we'll add the command to send the proxy here. This might move to
|
||||
// PDocAccessible constructor in PBrowser.
|
||||
sync COMProxy(IAccessibleHolder aDocCOMProxy)
|
||||
returns(IAccessibleHolder aParentCOMProxy);
|
||||
returns(IAccessibleHolder aParentCOMProxy, uint32_t aMsaaID);
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "Compatibility.h"
|
||||
#include "DocAccessible-inl.h"
|
||||
#include "mozilla/a11y/DocAccessibleChild.h"
|
||||
#include "mozilla/a11y/DocAccessibleParent.h"
|
||||
#include "EnumVariant.h"
|
||||
#include "nsAccUtils.h"
|
||||
@ -69,16 +70,14 @@ static const int32_t kIEnumVariantDisconnected = -1;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
AccessibleWrap::AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
Accessible(aContent, aDoc)
|
||||
#ifdef _WIN64
|
||||
, mID(kNoID)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
AccessibleWrap::~AccessibleWrap()
|
||||
{
|
||||
#ifdef _WIN64
|
||||
if (mID != kNoID)
|
||||
if (mID != kNoID && XRE_IsParentProcess())
|
||||
sIDGen.ReleaseID(mID);
|
||||
#endif
|
||||
}
|
||||
@ -90,7 +89,6 @@ NS_IMPL_ISUPPORTS_INHERITED0(AccessibleWrap, Accessible)
|
||||
void
|
||||
AccessibleWrap::Shutdown()
|
||||
{
|
||||
#ifdef _WIN64
|
||||
if (mID != kNoID) {
|
||||
auto doc = static_cast<DocAccessibleWrap*>(mDoc);
|
||||
MOZ_ASSERT(doc);
|
||||
@ -98,7 +96,6 @@ AccessibleWrap::Shutdown()
|
||||
doc->RemoveID(mID);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Accessible::Shutdown();
|
||||
}
|
||||
@ -1147,9 +1144,22 @@ AccessibleWrap::GetNativeInterface(void** aOutAccessible)
|
||||
NS_ADDREF_THIS();
|
||||
}
|
||||
|
||||
void
|
||||
AccessibleWrap::SetID(uint32_t aID)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsContentProcess());
|
||||
mID = aID;
|
||||
DocAccessibleWrap* doc = static_cast<DocAccessibleWrap*>(Document());
|
||||
DebugOnly<AccessibleWrap*> checkAcc = nullptr;
|
||||
MOZ_ASSERT(!(checkAcc = doc->GetAccessibleByID(aID)) ||
|
||||
checkAcc->GetExistingID() == aID);
|
||||
doc->AddID(aID, this);
|
||||
}
|
||||
|
||||
void
|
||||
AccessibleWrap::FireWinEvent(Accessible* aTarget, uint32_t aEventType)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
static_assert(sizeof(gWinEventMap)/sizeof(gWinEventMap[0]) == nsIAccessibleEvent::EVENT_LAST_ENTRY,
|
||||
"MSAA event map skewed");
|
||||
|
||||
@ -1246,6 +1256,13 @@ AccessibleWrap::GetChildIDFor(Accessible* aAccessible)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Content should use mID which has been generated by the chrome process.
|
||||
if (XRE_IsContentProcess() && !aAccessible->IsApplication()) {
|
||||
const uint32_t id = static_cast<AccessibleWrap*>(aAccessible)->mID;
|
||||
MOZ_ASSERT(id != kNoID);
|
||||
return id;
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
if (!aAccessible->Document() && !aAccessible->IsProxy())
|
||||
return 0;
|
||||
@ -1345,7 +1362,6 @@ AccessibleWrap::NativeAccessible(Accessible* aAccessible)
|
||||
return static_cast<IDispatch*>(msaaAccessible);
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
static Accessible*
|
||||
GetAccessibleInSubtree(DocAccessible* aDoc, uint32_t aID)
|
||||
{
|
||||
@ -1362,7 +1378,6 @@ GetAccessibleInSubtree(DocAccessible* aDoc, uint32_t aID)
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
static AccessibleWrap*
|
||||
GetProxiedAccessibleInSubtree(const DocAccessibleParent* aDoc, uint32_t aID)
|
||||
@ -1426,7 +1441,9 @@ AccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
|
||||
#ifdef _WIN64
|
||||
GetAccessibleInSubtree(document, static_cast<uint32_t>(aVarChild.lVal));
|
||||
#else
|
||||
document->GetAccessibleByUniqueIDInSubtree(uniqueID);
|
||||
XRE_IsContentProcess() ?
|
||||
GetAccessibleInSubtree(document, static_cast<uint32_t>(aVarChild.lVal)) :
|
||||
document->GetAccessibleByUniqueIDInSubtree(uniqueID);
|
||||
#endif
|
||||
|
||||
// If it is a document then just return an accessible.
|
||||
|
@ -179,17 +179,15 @@ public: // construction, destruction
|
||||
|
||||
static IDispatch* NativeAccessible(Accessible* aAccessible);
|
||||
|
||||
#ifdef _WIN64
|
||||
uint32_t GetExistingID() const { return mID; }
|
||||
static const uint32_t kNoID = 0;
|
||||
#endif
|
||||
// This is only valid to call in content
|
||||
void SetID(uint32_t aID);
|
||||
|
||||
protected:
|
||||
virtual ~AccessibleWrap();
|
||||
|
||||
#ifdef _WIN64
|
||||
uint32_t mID;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Return the wrapper for the document's proxy.
|
||||
|
@ -48,15 +48,10 @@ STDMETHODIMP
|
||||
DocAccessibleWrap::get_accParent(
|
||||
/* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispParent)
|
||||
{
|
||||
HRESULT hr = DocAccessible::get_accParent(ppdispParent);
|
||||
if (*ppdispParent) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
// We might be a top-level document in a content process.
|
||||
DocAccessibleChild* ipcDoc = IPCDoc();
|
||||
if (!ipcDoc) {
|
||||
return S_FALSE;
|
||||
return DocAccessible::get_accParent(ppdispParent);
|
||||
}
|
||||
IAccessible* dispParent = ipcDoc->GetParentIAccessible();
|
||||
if (!dispParent) {
|
||||
|
@ -40,13 +40,11 @@ public:
|
||||
/**
|
||||
* Manage the mapping from id to Accessible.
|
||||
*/
|
||||
#ifdef _WIN64
|
||||
void AddID(uint32_t aID, AccessibleWrap* aAcc)
|
||||
{ mIDToAccessibleMap.Put(aID, aAcc); }
|
||||
void RemoveID(uint32_t aID) { mIDToAccessibleMap.Remove(aID); }
|
||||
AccessibleWrap* GetAccessibleByID(uint32_t aID) const
|
||||
{ return mIDToAccessibleMap.Get(aID); }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// DocAccessible
|
||||
@ -58,9 +56,7 @@ protected:
|
||||
/*
|
||||
* This provides a mapping from 32 bit id to accessible objects.
|
||||
*/
|
||||
#ifdef _WIN64
|
||||
nsDataHashtable<nsUint32HashKey, AccessibleWrap*> mIDToAccessibleMap;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
|
Loading…
Reference in New Issue
Block a user