bug 1127402 - proxy RelationByType method r=davidb
authorTrevor Saunders <trev.saunders@gmail.com>
Thu, 29 Jan 2015 11:58:34 -0500
changeset 257675 5186614bfe01e21077b1c850d946d029d442edc8
parent 257674 baf1a5507fd6655ccd84cac4d5d7e83f3a1bdf2e
child 257676 88cd9db3cb3fdbaaf3709e8bd8c51d6be25537a7
push id721
push userjlund@mozilla.com
push dateTue, 21 Apr 2015 23:03:33 +0000
treeherdermozilla-release@d27c9211ebb3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdavidb
bugs1127402
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1127402 - proxy RelationByType method r=davidb
accessible/atk/AccessibleWrap.cpp
accessible/ipc/DocAccessibleChild.cpp
accessible/ipc/DocAccessibleChild.h
accessible/ipc/DocAccessibleParent.h
accessible/ipc/PDocAccessible.ipdl
accessible/ipc/ProxyAccessible.cpp
accessible/ipc/ProxyAccessible.h
--- a/accessible/atk/AccessibleWrap.cpp
+++ b/accessible/atk/AccessibleWrap.cpp
@@ -956,16 +956,50 @@ UpdateAtkRelation(RelationType aType, Ac
 }
 
 AtkRelationSet *
 refRelationSetCB(AtkObject *aAtkObj)
 {
   AtkRelationSet* relation_set =
     ATK_OBJECT_CLASS(parent_class)->ref_relation_set(aAtkObj);
 
+  const AtkRelationType typeMap[] = {
+#define RELATIONTYPE(gecko, s, atk, m, i) atk,
+#include "RelationTypeMap.h"
+#undef RELATIONTYPE
+  };
+
+  if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
+    nsTArray<RelationType> types;
+    nsTArray<nsTArray<ProxyAccessible*>> targetSets;
+    proxy->Relations(&types, &targetSets);
+
+    size_t relationCount = types.Length();
+    for (size_t i = 0; i < relationCount; i++) {
+      if (typeMap[static_cast<uint32_t>(types[i])] == ATK_RELATION_NULL)
+        continue;
+
+      size_t targetCount = targetSets[i].Length();
+      nsAutoTArray<AtkObject*, 5> wrappers;
+      for (size_t j = 0; j < targetCount; j++)
+        wrappers.AppendElement(GetWrapperFor(targetSets[i][j]));
+
+      AtkRelationType atkType = typeMap[static_cast<uint32_t>(types[i])];
+      AtkRelation* atkRelation =
+        atk_relation_set_get_relation_by_type(relation_set, atkType);
+      if (atkRelation)
+        atk_relation_set_remove(relation_set, atkRelation);
+
+      atkRelation = atk_relation_new(wrappers.Elements(), wrappers.Length(),
+                                     atkType);
+      atk_relation_set_add(relation_set, atkRelation);
+      g_object_unref(atkRelation);
+    }
+  }
+
   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   if (!accWrap)
     return relation_set;
 
 #define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \
   UpdateAtkRelation(RelationType::geckoType, accWrap, atkType, relation_set);
 
 #include "RelationTypeMap.h"
--- a/accessible/ipc/DocAccessibleChild.cpp
+++ b/accessible/ipc/DocAccessibleChild.cpp
@@ -3,16 +3,17 @@
 /* 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 "DocAccessibleChild.h"
 
 #include "Accessible-inl.h"
 #include "ProxyAccessible.h"
+#include "Relation.h"
 
 #include "nsIPersistentProperties2.h"
 #include "nsISimpleEnumerator.h"
 
 namespace mozilla {
 namespace a11y {
 
 static uint32_t
@@ -152,16 +153,66 @@ DocAccessibleChild::RecvAttributes(const
 
     aAttributes->AppendElement(Attribute(name, value));
     }
 
   return true;
 }
 
 bool
+DocAccessibleChild::RecvRelationByType(const uint64_t& aID,
+                                       const uint32_t& aType,
+                                       nsTArray<uint64_t>* aTargets)
+{
+  Accessible* acc = mDoc->GetAccessibleByUniqueID((void*)aID);
+  if (!acc)
+    return false;
+
+  auto type = static_cast<RelationType>(aType);
+  Relation rel = acc->RelationByType(type);
+  while (Accessible* target = rel.Next())
+    aTargets->AppendElement(reinterpret_cast<uintptr_t>(target));
+
+  return true;
+}
+
+static void
+AddRelation(Accessible* aAcc, RelationType aType,
+            nsTArray<RelationTargets>* aTargets)
+{
+  Relation rel = aAcc->RelationByType(aType);
+  nsTArray<uint64_t> targets;
+  while (Accessible* target = rel.Next())
+    targets.AppendElement(reinterpret_cast<uintptr_t>(target));
+
+  if (!targets.IsEmpty()) {
+    RelationTargets* newRelation =
+      aTargets->AppendElement(RelationTargets(static_cast<uint32_t>(aType),
+                                              nsTArray<uint64_t>()));
+    newRelation->Targets().SwapElements(targets);
+  }
+}
+
+bool
+DocAccessibleChild::RecvRelations(const uint64_t& aID,
+                                  nsTArray<RelationTargets>* aRelations)
+{
+  Accessible* acc = mDoc->GetAccessibleByUniqueID((void*)aID);
+  if (!aID)
+    return false;
+
+#define RELATIONTYPE(gecko, s, a, m, i) AddRelation(acc, RelationType::gecko, aRelations);
+
+#include "RelationTypeMap.h"
+#undef RELATIONTYPE
+
+  return true;
+}
+
+bool
 DocAccessibleChild::RecvTextSubstring(const uint64_t& aID,
                                       const int32_t& aStartOffset,
                                       const int32_t& aEndOffset,
                                       nsString* aText)
 {
   HyperTextAccessible* acc = IdToHyperTextAccessible(aID);
   if (!acc) {
     return true;
--- a/accessible/ipc/DocAccessibleChild.h
+++ b/accessible/ipc/DocAccessibleChild.h
@@ -50,18 +50,24 @@ public:
   virtual bool RecvName(const uint64_t& aID, nsString* aName) MOZ_OVERRIDE;
 
   virtual bool RecvValue(const uint64_t& aID, nsString* aValue) MOZ_OVERRIDE;
   
   /*
    * Get the description for the accessible with given id.
    */
   virtual bool RecvDescription(const uint64_t& aID, nsString* aDesc) MOZ_OVERRIDE;
+  virtual bool RecvRelationByType(const uint64_t& aID, const uint32_t& aType,
+                                  nsTArray<uint64_t>* aTargets) MOZ_OVERRIDE;
+  virtual bool RecvRelations(const uint64_t& aID,
+                             nsTArray<RelationTargets>* aRelations)
+    MOZ_OVERRIDE;
 
-  virtual bool RecvAttributes(const uint64_t& aID, nsTArray<Attribute> *aAttributes) MOZ_OVERRIDE;
+  virtual bool RecvAttributes(const uint64_t& aID,
+                              nsTArray<Attribute> *aAttributes) MOZ_OVERRIDE;
   virtual bool RecvTextSubstring(const uint64_t& aID,
                                  const int32_t& aStartOffset,
                                  const int32_t& aEndOffset, nsString* aText)
     MOZ_OVERRIDE;
 
   virtual bool RecvGetTextAfterOffset(const uint64_t& aID,
                                       const int32_t& aOffset,
                                       const AccessibleTextBoundary& aBoundaryType,
--- a/accessible/ipc/DocAccessibleParent.h
+++ b/accessible/ipc/DocAccessibleParent.h
@@ -77,16 +77,25 @@ public:
   }
 
   void RemoveAccessible(ProxyAccessible* aAccessible)
   {
     MOZ_ASSERT(mAccessibles.GetEntry(aAccessible->ID()));
     mAccessibles.RemoveEntry(aAccessible->ID());
   }
 
+  /**
+   * Return the accessible for given id.
+   */
+  ProxyAccessible* GetAccessible(uintptr_t aID) const
+  {
+    ProxyEntry* e = mAccessibles.GetEntry(aID);
+    return e ? e->mProxy : nullptr;
+  }
+
 private:
 
   class ProxyEntry : public PLDHashEntryHdr
   {
   public:
     explicit ProxyEntry(const void*) : mProxy(nullptr) {}
     ProxyEntry(ProxyEntry&& aOther) :
       mProxy(aOther.mProxy) { aOther.mProxy = nullptr; }
--- a/accessible/ipc/PDocAccessible.ipdl
+++ b/accessible/ipc/PDocAccessible.ipdl
@@ -27,16 +27,22 @@ struct ShowEventData
 };
 
 struct Attribute
 {
   nsCString Name;
   nsString Value;
 };
 
+struct RelationTargets
+{
+  uint32_t Type;
+  uint64_t[] Targets;
+};
+
 prio(normal upto high) sync protocol PDocAccessible
 {
   manager PContent;
 
 parent:
   __delete__();
 
   /*
@@ -49,16 +55,19 @@ parent:
 
 child:
   // Accessible
   prio(high) sync State(uint64_t aID) returns(uint64_t states);
   prio(high) sync Name(uint64_t aID) returns(nsString name);
   prio(high) sync Value(uint64_t aID) returns(nsString value);
   prio(high) sync Description(uint64_t aID) returns(nsString desc);
   prio(high) sync Attributes(uint64_t aID) returns(Attribute[] attributes);
+  prio(high) sync RelationByType(uint64_t aID, uint32_t aRelationType)
+    returns(uint64_t[] targets);
+  prio(high) sync Relations(uint64_t aID) returns(RelationTargets[] relations);
 
   // AccessibleText
 
   // TextSubstring is getText in IDL.
   prio(high) sync TextSubstring(uint64_t aID, int32_t aStartOffset, int32_t
                                 aEndOffset) returns(nsString aText);
   prio(high) sync GetTextAfterOffset(uint64_t aID, int32_t aOffset, AccessibleTextBoundary aBoundaryType)
     returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
--- a/accessible/ipc/ProxyAccessible.cpp
+++ b/accessible/ipc/ProxyAccessible.cpp
@@ -3,16 +3,17 @@
 /* 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 "ProxyAccessible.h"
 #include "DocAccessibleParent.h"
 #include "mozilla/unused.h"
 #include "mozilla/a11y/Platform.h"
+#include "RelationType.h"
 #include "mozilla/a11y/Role.h"
 
 namespace mozilla {
 namespace a11y {
 
 void
 ProxyAccessible::Shutdown()
 {
@@ -97,16 +98,62 @@ ProxyAccessible::Description(nsString& a
 }
 
 void
 ProxyAccessible::Attributes(nsTArray<Attribute> *aAttrs) const
 {
   unused << mDoc->SendAttributes(mID, aAttrs);
 }
 
+nsTArray<ProxyAccessible*>
+ProxyAccessible::RelationByType(RelationType aType) const
+{
+  nsTArray<uint64_t> targetIDs;
+  unused << mDoc->SendRelationByType(mID, static_cast<uint32_t>(aType),
+                                     &targetIDs);
+
+  size_t targetCount = targetIDs.Length();
+  nsTArray<ProxyAccessible*> targets(targetCount);
+  for (size_t i = 0; i < targetCount; i++)
+    if (ProxyAccessible* proxy = mDoc->GetAccessible(targetIDs[i]))
+      targets.AppendElement(proxy);
+
+  return Move(targets);
+}
+
+void
+ProxyAccessible::Relations(nsTArray<RelationType>* aTypes,
+                           nsTArray<nsTArray<ProxyAccessible*>>* aTargetSets)
+  const
+{
+  nsTArray<RelationTargets> ipcRelations;
+  unused << mDoc->SendRelations(mID, &ipcRelations);
+
+  size_t relationCount = ipcRelations.Length();
+  aTypes->SetCapacity(relationCount);
+  aTargetSets->SetCapacity(relationCount);
+  for (size_t i = 0; i < relationCount; i++) {
+    uint32_t type = ipcRelations[i].Type();
+    if (type > static_cast<uint32_t>(RelationType::LAST))
+      continue;
+
+    size_t targetCount = ipcRelations[i].Targets().Length();
+    nsTArray<ProxyAccessible*> targets(targetCount);
+    for (size_t j = 0; j < targetCount; j++)
+      if (ProxyAccessible* proxy = mDoc->GetAccessible(ipcRelations[i].Targets()[j]))
+        targets.AppendElement(proxy);
+
+    if (targets.IsEmpty())
+      continue;
+
+    aTargetSets->AppendElement(Move(targets));
+    aTypes->AppendElement(static_cast<RelationType>(type));
+  }
+}
+
 void
 ProxyAccessible::TextSubstring(int32_t aStartOffset, int32_t aEndOfset,
                                nsString& aText) const
 {
   unused << mDoc->SendTextSubstring(mID, aStartOffset, aEndOfset, &aText);
 }
 
 void
--- a/accessible/ipc/ProxyAccessible.h
+++ b/accessible/ipc/ProxyAccessible.h
@@ -12,16 +12,17 @@
 #include "nsString.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 namespace a11y {
 
 class Attribute;
 class DocAccessibleParent;
+enum class RelationType;
 
 class ProxyAccessible
 {
 public:
 
   ProxyAccessible(uint64_t aID, ProxyAccessible* aParent,
                   DocAccessibleParent* aDoc, role aRole) :
      mParent(aParent), mDoc(aDoc), mWrapper(0), mID(aID), mRole(aRole),
@@ -83,16 +84,27 @@ public:
   void Description(nsString& aDesc) const;
 
   /**
    * Get the set of attributes on the proxied accessible.
    */
   void Attributes(nsTArray<Attribute> *aAttrs) const;
 
   /**
+   * Return set of targets of given relation type.
+   */
+  nsTArray<ProxyAccessible*> RelationByType(RelationType aType) const;
+
+  /**
+   * Get all relations for this accessible.
+   */
+  void Relations(nsTArray<RelationType>* aTypes,
+                 nsTArray<nsTArray<ProxyAccessible*>>* aTargetSets) const;
+
+  /**
    * Get the text between the given offsets.
    */
   void TextSubstring(int32_t aStartOffset, int32_t aEndOfset,
                      nsString& aText) const;
 
   void GetTextAfterOffset(int32_t aOffset, AccessibleTextBoundary aBoundaryType,
                           nsString& aText, int32_t* aStartOffset,
                           int32_t* aEndOffset);