Bug 1339128 - reference parent proxy by id r=eeejay a=gchang
authorTrevor Saunders <tbsaunde@tbsaunde.org>
Mon, 13 Feb 2017 11:56:53 -0500
changeset 376299 a6d3ee554e58f1439e0111da53753d37433c7ccc
parent 376298 661e35b83224d2962961d955c834d4c08ce8320d
child 376300 35ef506e005a3bc7f42637debfada1d3e09d7e5a
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerseeejay, gchang
bugs1339128
milestone53.0a2
Bug 1339128 - reference parent proxy by id r=eeejay a=gchang
accessible/ipc/DocAccessibleParent.cpp
accessible/ipc/DocAccessibleParent.h
accessible/ipc/ProxyAccessibleBase.cpp
accessible/ipc/ProxyAccessibleBase.h
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -405,17 +405,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
@@ -87,17 +87,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
@@ -164,12 +164,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: