bug 1339128 - reference parent proxy by id r=eeejay
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -420,17 +420,17 @@ DocAccessibleParent::AddChildDoc(DocAcce
// 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 IPC_FAIL(this, "binding to proxy that can't be a outerDoc!");
}
- aChildDoc->mParent = outerDoc;
+ aChildDoc->SetParent(outerDoc);
outerDoc->SetChildDoc(aChildDoc);
mChildDocs.AppendElement(aChildDoc);
aChildDoc->mParentDoc = this;
if (aCreating) {
ProxyCreated(aChildDoc, Interfaces::DOCUMENT | Interfaces::HYPERTEXT);
}
--- a/accessible/ipc/DocAccessibleParent.h
+++ b/accessible/ipc/DocAccessibleParent.h
@@ -90,17 +90,17 @@ public:
virtual mozilla::ipc::IPCResult RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID) override;
void Unbind()
{
if (DocAccessibleParent* parent = ParentDoc()) {
parent->RemoveChildDoc(this);
}
- mParent = nullptr;
+ SetParent(nullptr);
}
virtual mozilla::ipc::IPCResult RecvShutdown() override;
void Destroy();
virtual void ActorDestroy(ActorDestroyReason aWhy) override
{
MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
if (!mShutdown)
--- a/accessible/ipc/ProxyAccessibleBase.cpp
+++ b/accessible/ipc/ProxyAccessibleBase.cpp
@@ -162,12 +162,53 @@ ProxyAccessibleBase<Derived>::OuterDocOf
if (!frame)
return nullptr;
DocAccessible* chromeDoc = GetExistingDocAccessible(frame->OwnerDoc());
return chromeDoc ? chromeDoc->GetAccessible(frame) : nullptr;
}
+template<class Derived>
+void
+ProxyAccessibleBase<Derived>::SetParent(Derived* aParent)
+{
+ MOZ_ASSERT(IsDoc(), "we should only reparent documents");
+ if (!aParent) {
+ mParent = kNoParent;
+ } else {
+ MOZ_ASSERT(!aParent->IsDoc());
+ mParent = aParent->ID();
+ }
+}
+
+template<class Derived>
+Derived*
+ProxyAccessibleBase<Derived>::Parent() const
+{
+ if (mParent == kNoParent) {
+ return nullptr;
+ }
+
+ // if we are not a document then are parent is another proxy in the same
+ // document. That means we can just ask our document for the proxy with our
+ // parent id.
+ if (!IsDoc()) {
+ return Document()->GetAccessible(mParent);
+ }
+
+ // If we are a top level document then our parent is not a proxy.
+ if (AsDoc()->IsTopLevel()) {
+ return nullptr;
+ }
+
+ // Finally if we are a non top level document then our parent id is for a
+ // proxy in our parent document so get the proxy from there.
+ DocAccessibleParent* parentDoc = AsDoc()->ParentDoc();
+ MOZ_ASSERT(parentDoc);
+ MOZ_ASSERT(mParent);
+ return parentDoc->GetAccessible(mParent);
+}
+
template class ProxyAccessibleBase<ProxyAccessible>;
} // namespace a11y
} // namespace mozilla
--- a/accessible/ipc/ProxyAccessibleBase.h
+++ b/accessible/ipc/ProxyAccessibleBase.h
@@ -85,17 +85,17 @@ public:
* 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; }
+ Derived* Parent() const;
Accessible* OuterDocOfRemoteBrowser() const;
/**
* Get the role of the accessible we're proxying.
*/
role Role() const { return mRole; }
@@ -153,39 +153,42 @@ public:
mRole == roles::GRID_CELL ||
mRole == roles::MATHML_CELL);
}
protected:
ProxyAccessibleBase(uint64_t aID, Derived* aParent,
DocAccessibleParent* aDoc, role aRole,
uint32_t aInterfaces)
- : mParent(aParent)
+ : mParent(aParent->ID())
, 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),
+ mParent(kNoParent), mDoc(aThisAsDoc), mWrapper(0), mID(0),
mRole(roles::DOCUMENT), mOuterDoc(false), mIsDoc(true), mHasValue(false),
mIsHyperLink(false), mIsHyperText(false)
{}
protected:
- Derived* mParent;
+ void SetParent(Derived* aParent);
private:
+ uintptr_t mParent;
+ static const uintptr_t kNoParent = UINTPTR_MAX;
+
friend Derived;
nsTArray<Derived*> mChildren;
DocAccessibleParent* mDoc;
uintptr_t mWrapper;
uint64_t mID;
protected: