Bug 1314707: Replace PDocAccessible::SendCOMProxy with new parameter to PDocAccessibleConstructor and async RecvParentCOMProxy call in child. Sending of a11y events from child to parent is now deferred until DocAccessibleChild::RecvParentCOMProxy is called; r=tbsaunde

--HG--
extra : amend_source : 59d080ee7370d62211d7c9f8ca5ef17870bfe500
This commit is contained in:
Aaron Klotz 2016-11-09 15:24:58 -07:00
Родитель 8d534ac19c
Коммит 37a3b973b9
16 изменённых файлов: 367 добавлений и 41 удалений

Просмотреть файл

@ -514,19 +514,19 @@ DocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
DocAccessibleChild* ipcDoc = new DocAccessibleChild(docAcc);
docAcc->SetIPCDoc(ipcDoc);
#if defined(XP_WIN)
IAccessibleHolder holder(CreateHolderFromAccessible(docAcc));
#endif
static_cast<TabChild*>(tabChild.get())->
SendPDocAccessibleConstructor(ipcDoc, nullptr, 0,
#if defined(XP_WIN)
AccessibleWrap::GetChildIDFor(docAcc)
AccessibleWrap::GetChildIDFor(docAcc),
holder
#else
0
0, 0
#endif
);
#if defined(XP_WIN)
IAccessibleHolder holder(CreateHolderFromAccessible(docAcc));
ipcDoc->SendCOMProxy(holder);
#endif
}
}
}

Просмотреть файл

@ -426,9 +426,10 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
static_cast<TabChild*>(tabChild.get())->
SendPDocAccessibleConstructor(ipcDoc, parentIPCDoc, id,
#if defined(XP_WIN)
AccessibleWrap::GetChildIDFor(childDoc)
AccessibleWrap::GetChildIDFor(childDoc),
IAccessibleHolder()
#else
0
0, 0
#endif
);
}

Просмотреть файл

@ -89,7 +89,7 @@ DocAccessibleChildBase::ShowEvent(AccShowEvent* aShowEvent)
nsTArray<AccessibleData> shownTree;
ShowEventData data(parentID, idxInParent, shownTree);
SerializeTree(aShowEvent->GetAccessible(), data.NewTree());
SendShowEvent(data, aShowEvent->IsFromUserInput());
MaybeSendShowEvent(data, aShowEvent->IsFromUserInput());
}
} // namespace a11y

Просмотреть файл

@ -9,6 +9,7 @@
#include "mozilla/a11y/DocAccessible.h"
#include "mozilla/a11y/PDocAccessibleChild.h"
#include "mozilla/Unused.h"
#include "nsISupportsImpl.h"
namespace mozilla {
@ -61,6 +62,9 @@ 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); }
DocAccessible* mDoc;
};

Просмотреть файл

@ -461,25 +461,24 @@ DocAccessibleParent::GetXPCAccessible(ProxyAccessible* aProxy)
#if defined(XP_WIN)
/**
* @param aCOMProxy COM Proxy to the document in the content process.
* @param aParentCOMProxy COM Proxy to the OuterDocAccessible that is
* the parent of the document. The content process will use this
* proxy when traversing up across the content/chrome boundary.
*/
bool
DocAccessibleParent::RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
IAccessibleHolder* aParentCOMProxy)
void
DocAccessibleParent::SetCOMProxy(const RefPtr<IAccessible>& aCOMProxy)
{
RefPtr<IAccessible> ptr(aCOMProxy.Get());
SetCOMInterface(ptr);
SetCOMInterface(aCOMProxy);
Accessible* outerDoc = OuterDocOfRemoteBrowser();
MOZ_ASSERT(outerDoc);
IAccessible* rawNative = nullptr;
if (outerDoc) {
outerDoc->GetNativeInterface((void**) &rawNative);
MOZ_ASSERT(rawNative);
}
aParentCOMProxy->Set(IAccessibleHolder::COMPtrType(rawNative));
return true;
IAccessibleHolder::COMPtrType ptr(rawNative);
IAccessibleHolder holder(Move(ptr));
Unused << SendParentCOMProxy(holder);
}
#endif // defined(XP_WIN)

Просмотреть файл

@ -144,8 +144,7 @@ public:
{ return mChildDocs[aIdx]; }
#if defined(XP_WIN)
virtual bool RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
IAccessibleHolder* aParentCOMProxy) override;
void SetCOMProxy(const RefPtr<IAccessible>& aCOMProxy);
#endif
private:

49
accessible/ipc/IPCTypes.h Normal file
Просмотреть файл

@ -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

Просмотреть файл

@ -29,6 +29,10 @@ else:
'/accessible/other',
]
EXPORTS.mozilla.a11y += [
'IPCTypes.h',
]
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']

Просмотреть файл

@ -30,14 +30,116 @@ DocAccessibleChild::~DocAccessibleChild()
MOZ_COUNT_DTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
}
void
DocAccessibleChild::SendCOMProxy(const IAccessibleHolder& aProxy)
bool
DocAccessibleChild::RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy)
{
IAccessibleHolder parentProxy;
PDocAccessibleChild::SendCOMProxy(aProxy, &parentProxy);
mParentProxy.reset(parentProxy.Release());
MOZ_ASSERT(!mParentProxy && !aParentCOMProxy.IsNull());
mParentProxy.reset(const_cast<IAccessibleHolder&>(aParentCOMProxy).Release());
for (uint32_t i = 0, l = mDeferredEvents.Length(); i < l; ++i) {
mDeferredEvents[i]->Dispatch(this);
}
mDeferredEvents.Clear();
return true;
}
bool
DocAccessibleChild::SendEvent(const uint64_t& aID, const uint32_t& aType)
{
if (mParentProxy) {
return PDocAccessibleChild::SendEvent(aID, aType);
}
mDeferredEvents.AppendElement(MakeUnique<SerializedEvent>(aID, aType));
return false;
}
void
DocAccessibleChild::MaybeSendShowEvent(ShowEventData& aData, bool aFromUser)
{
if (mParentProxy) {
Unused << SendShowEvent(aData, aFromUser);
return;
}
mDeferredEvents.AppendElement(MakeUnique<SerializedShow>(aData, aFromUser));
}
bool
DocAccessibleChild::SendHideEvent(const uint64_t& aRootID,
const bool& aFromUser)
{
if (mParentProxy) {
return PDocAccessibleChild::SendHideEvent(aRootID, aFromUser);
}
mDeferredEvents.AppendElement(MakeUnique<SerializedHide>(aRootID, aFromUser));
return true;
}
bool
DocAccessibleChild::SendStateChangeEvent(const uint64_t& aID,
const uint64_t& aState,
const bool& aEnabled)
{
if (mParentProxy) {
return PDocAccessibleChild::SendStateChangeEvent(aID, aState, aEnabled);
}
mDeferredEvents.AppendElement(MakeUnique<SerializedStateChange>(aID, aState,
aEnabled));
return true;
}
bool
DocAccessibleChild::SendCaretMoveEvent(const uint64_t& aID,
const int32_t& aOffset)
{
if (mParentProxy) {
return PDocAccessibleChild::SendCaretMoveEvent(aID, aOffset);
}
mDeferredEvents.AppendElement(MakeUnique<SerializedCaretMove>(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 (mParentProxy) {
return PDocAccessibleChild::SendTextChangeEvent(aID, aStr, aStart,
aLen, aIsInsert, aFromUser);
}
mDeferredEvents.AppendElement(MakeUnique<SerializedTextChange>(aID, aStr,
aStart, aLen,
aIsInsert,
aFromUser));
return true;
}
bool
DocAccessibleChild::SendSelectionEvent(const uint64_t& aID,
const uint64_t& aWidgetID,
const uint32_t& aType)
{
if (mParentProxy) {
return PDocAccessibleChild::SendSelectionEvent(aID, aWidgetID, aType);
}
mDeferredEvents.AppendElement(MakeUnique<SerializedSelection>(aID, aWidgetID,
aType));
return true;
}
} // namespace a11y
} // namespace mozilla

Просмотреть файл

@ -24,11 +24,173 @@ public:
explicit DocAccessibleChild(DocAccessible* aDoc);
~DocAccessibleChild();
void SendCOMProxy(const IAccessibleHolder& aProxy);
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);
protected:
virtual void MaybeSendShowEvent(ShowEventData& aData, bool aFromUser) override;
private:
/**
* 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
{
virtual void Dispatch(DocAccessibleChild* aIPCDoc) = 0;
virtual ~DeferredEvent() {}
};
struct SerializedShow final : public DeferredEvent
{
SerializedShow(ShowEventData& aEventData, bool aFromUser)
: 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(uint64_t aRootID, bool aFromUser)
: 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(uint64_t aID, uint64_t aState, bool aEnabled)
: 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(uint64_t aID, int32_t aOffset)
: 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(uint64_t aID, const nsString& aStr, int32_t aStart,
uint32_t aLen, bool aIsInsert, bool aFromUser)
: 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(uint64_t aID, uint64_t aWidgetID, uint32_t aType)
: 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 SerializedEvent final : public DeferredEvent
{
SerializedEvent(uint64_t aID, uint32_t aType)
: mID(aID)
, mType(aType)
{}
void Dispatch(DocAccessibleChild* aIPCDoc) override
{
Unused << aIPCDoc->SendEvent(mID, mType);
}
uint64_t mID;
uint32_t mType;
};
mscom::ProxyUniquePtr<IAccessible> mParentProxy;
nsTArray<UniquePtr<DeferredEvent>> mDeferredEvents;
};
} // namespace a11y

Просмотреть файл

@ -61,12 +61,9 @@ parent:
*/
async BindChildDoc(PDocAccessible aChildDoc, uint64_t aID);
// 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);
child:
async ParentCOMProxy(IAccessibleHolder aParentCOMProxy);
async __delete__();
};

Просмотреть файл

@ -76,6 +76,7 @@ using nsSizeMode from "nsIWidgetListener.h";
using mozilla::widget::CandidateWindowPosition from "ipc/nsGUIEventIPC.h";
using class mozilla::NativeEventData from "ipc/nsGUIEventIPC.h";
using mozilla::FontRange from "ipc/nsGUIEventIPC.h";
using mozilla::a11y::IAccessibleHolder from "mozilla/a11y/IPCTypes.h";
namespace mozilla {
namespace dom {
@ -140,10 +141,11 @@ parent:
* aParentDoc is the accessible document it was created in if any, and
* aParentAcc is the id of the accessible in that document the new document
* is a child of. aMsaaID is the MSAA id for this content process, and
* is only valid on Windows. Set to 0 on other platforms.
* is only valid on Windows. Set to 0 on other platforms. aDocCOMProxy
* is also Windows-specific and should be set to 0 on other platforms.
*/
async PDocAccessible(nullable PDocAccessible aParentDoc, uint64_t aParentAcc,
uint32_t aMsaaID);
uint32_t aMsaaID, IAccessibleHolder aDocCOMProxy);
/*
* Creates a new remoted nsIWidget connection for windowed plugins

Просмотреть файл

@ -1981,7 +1981,7 @@ TabChild::RecvPasteTransferable(const IPCDataTransfer& aDataTransfer,
a11y::PDocAccessibleChild*
TabChild::AllocPDocAccessibleChild(PDocAccessibleChild*, const uint64_t&,
const uint32_t&)
const uint32_t&, const IAccessibleHolder&)
{
MOZ_ASSERT(false, "should never call this!");
return nullptr;

Просмотреть файл

@ -441,7 +441,7 @@ public:
virtual PDocAccessibleChild*
AllocPDocAccessibleChild(PDocAccessibleChild*, const uint64_t&,
const uint32_t&) override;
const uint32_t&, const IAccessibleHolder&) override;
virtual bool DeallocPDocAccessibleChild(PDocAccessibleChild*) override;

Просмотреть файл

@ -870,7 +870,8 @@ TabParent::SetDocShell(nsIDocShell *aDocShell)
a11y::PDocAccessibleParent*
TabParent::AllocPDocAccessibleParent(PDocAccessibleParent* aParent,
const uint64_t&, const uint32_t&)
const uint64_t&, const uint32_t&,
const IAccessibleHolder&)
{
#ifdef ACCESSIBILITY
return new a11y::DocAccessibleParent();
@ -892,7 +893,8 @@ bool
TabParent::RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc,
PDocAccessibleParent* aParentDoc,
const uint64_t& aParentID,
const uint32_t& aMsaaID)
const uint32_t& aMsaaID,
const IAccessibleHolder& aDocCOMProxy)
{
#ifdef ACCESSIBILITY
auto doc = static_cast<a11y::DocAccessibleParent*>(aDoc);
@ -908,6 +910,7 @@ TabParent::RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc,
auto parentDoc = static_cast<a11y::DocAccessibleParent*>(aParentDoc);
bool added = parentDoc->AddChildDoc(doc, aParentID);
#ifdef XP_WIN
MOZ_ASSERT(aDocCOMProxy.IsNull());
if (added) {
a11y::WrapperFor(doc)->SetID(aMsaaID);
}
@ -926,6 +929,9 @@ TabParent::RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc,
a11y::DocManager::RemoteDocAdded(doc);
#ifdef XP_WIN
a11y::WrapperFor(doc)->SetID(aMsaaID);
MOZ_ASSERT(!aDocCOMProxy.IsNull());
RefPtr<IAccessible> proxy(aDocCOMProxy.Get());
doc->SetCOMProxy(proxy);
#endif
}
#endif

Просмотреть файл

@ -353,7 +353,7 @@ public:
virtual PDocAccessibleParent*
AllocPDocAccessibleParent(PDocAccessibleParent*, const uint64_t&,
const uint32_t&) override;
const uint32_t&, const IAccessibleHolder&) override;
virtual bool DeallocPDocAccessibleParent(PDocAccessibleParent*) override;
@ -361,7 +361,8 @@ public:
RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc,
PDocAccessibleParent* aParentDoc,
const uint64_t& aParentID,
const uint32_t& aMsaaID) override;
const uint32_t& aMsaaID,
const IAccessibleHolder& aDocCOMProxy) override;
/**
* Return the top level doc accessible parent for this tab.