Bug 1187609 - Check for proxies in mozAccessible role, subrole r=tbsaunde
authorLorien Hu <lorien@lorienhu.com>
Tue, 04 Aug 2015 14:56:07 -0400
changeset 287834 081d48ca7e97320a209ed4af829b85a0caa8d76b
parent 287833 4a9d48b58545fa05fc488f3e5c163af2725cbca3
child 287835 3cfa0ff6f2e55c771a8d33c2cc93dbb2ea2c8f05
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstbsaunde
bugs1187609
milestone42.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 1187609 - Check for proxies in mozAccessible role, subrole r=tbsaunde
accessible/ipc/DocAccessibleChild.cpp
accessible/ipc/DocAccessibleChild.h
accessible/ipc/PDocAccessible.ipdl
accessible/ipc/ProxyAccessible.cpp
accessible/ipc/ProxyAccessible.h
accessible/mac/mozAccessible.mm
--- a/accessible/ipc/DocAccessibleChild.cpp
+++ b/accessible/ipc/DocAccessibleChild.cpp
@@ -269,16 +269,59 @@ DocAccessibleChild::RecvRelations(const 
 
 #include "RelationTypeMap.h"
 #undef RELATIONTYPE
 
   return true;
 }
 
 bool
+DocAccessibleChild::RecvIsSearchbox(const uint64_t& aID, bool* aRetVal)
+{
+  Accessible* acc = IdToAccessible(aID);
+  if (!acc)
+    return true;
+
+  *aRetVal = acc->IsSearchbox();
+  return true;
+}
+
+bool
+DocAccessibleChild::RecvLandmarkRole(const uint64_t& aID, nsString* aLandmark)
+{
+  Accessible* acc = IdToAccessible(aID);
+  if (!acc) {
+    return true;
+  }
+
+  if (nsIAtom* roleAtom = acc->LandmarkRole()) {
+    roleAtom->ToString(*aLandmark);
+  }
+
+  return true;
+}
+
+bool
+DocAccessibleChild::RecvARIARoleAtom(const uint64_t& aID, nsString* aRole)
+{
+  Accessible* acc = IdToAccessible(aID);
+  if (!acc) {
+    return true;
+  }
+
+  if (nsRoleMapEntry* roleMap = acc->ARIARoleMap()) {
+    if (nsIAtom* roleAtom = *(roleMap->roleAtom)) {
+      roleAtom->ToString(*aRole);
+    }
+  }
+
+  return true;
+}
+
+bool
 DocAccessibleChild::RecvCaretOffset(const uint64_t& aID, int32_t* aOffset)
 {
   HyperTextAccessible* acc = IdToHyperTextAccessible(aID);
   *aOffset = acc && acc->IsTextRole() ? acc->CaretOffset() : 0;
   return true;
 }
 
 bool
--- a/accessible/ipc/DocAccessibleChild.h
+++ b/accessible/ipc/DocAccessibleChild.h
@@ -64,27 +64,33 @@ public:
   virtual bool RecvState(const uint64_t& aID, uint64_t* aState) override;
 
   /*
    * Get the name for the accessible with given id.
    */
   virtual bool RecvName(const uint64_t& aID, nsString* aName) override;
 
   virtual bool RecvValue(const uint64_t& aID, nsString* aValue) override;
-  
+
   /*
    * Get the description for the accessible with given id.
    */
   virtual bool RecvDescription(const uint64_t& aID, nsString* aDesc) override;
   virtual bool RecvRelationByType(const uint64_t& aID, const uint32_t& aType,
                                   nsTArray<uint64_t>* aTargets) override;
   virtual bool RecvRelations(const uint64_t& aID,
                              nsTArray<RelationTargets>* aRelations)
     override;
 
+  virtual bool RecvIsSearchbox(const uint64_t& aID, bool* aRetVal) override;
+
+  virtual bool RecvLandmarkRole(const uint64_t& aID, nsString* aLandmark) override;
+
+  virtual bool RecvARIARoleAtom(const uint64_t& aID, nsString* aRole) override;
+
   virtual bool RecvAttributes(const uint64_t& aID,
                               nsTArray<Attribute> *aAttributes) override;
 
   virtual bool RecvCaretOffset(const uint64_t& aID, int32_t* aOffset)
     override;
   virtual bool RecvSetCaretOffset(const uint64_t& aID, const int32_t& aOffset,
                                   bool* aValid) override;
 
--- a/accessible/ipc/PDocAccessible.ipdl
+++ b/accessible/ipc/PDocAccessible.ipdl
@@ -75,16 +75,19 @@ child:
   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);
+  prio(high) sync IsSearchbox(uint64_t aID) returns(bool retval);
+  prio(high) sync LandmarkRole(uint64_t aID) returns(nsString landmark);
+  prio(high) sync ARIARoleAtom(uint64_t aID) returns(nsString role);
 
   // AccessibleText
 
   // TextSubstring is getText in IDL.
   prio(high) sync CaretOffset(uint64_t aID) returns(int32_t aOffset);
   prio(high) sync SetCaretOffset(uint64_t aID, int32_t aOffset) returns (bool aValid);
   prio(high) sync CharacterCount(uint64_t aID) returns(int32_t aCount);
   prio(high) sync SelectionCount(uint64_t aID) returns(int32_t aCount);
--- a/accessible/ipc/ProxyAccessible.cpp
+++ b/accessible/ipc/ProxyAccessible.cpp
@@ -148,16 +148,40 @@ ProxyAccessible::Relations(nsTArray<Rela
     if (targets.IsEmpty())
       continue;
 
     aTargetSets->AppendElement(Move(targets));
     aTypes->AppendElement(static_cast<RelationType>(type));
   }
 }
 
+bool
+ProxyAccessible::IsSearchbox() const
+{
+  bool retVal = false;
+  unused << mDoc->SendIsSearchbox(mID, &retVal);
+  return retVal;
+}
+
+nsIAtom*
+ProxyAccessible::LandmarkRole() const
+{
+  nsString landmark;
+  unused << mDoc->SendLandmarkRole(mID, &landmark);
+  return NS_GetStaticAtom(landmark);
+}
+
+nsIAtom*
+ProxyAccessible::ARIARoleAtom() const
+{
+  nsString role;
+  unused << mDoc->SendARIARoleAtom(mID, &role);
+  return NS_GetStaticAtom(role);
+}
+
 int32_t
 ProxyAccessible::CaretOffset()
 {
   int32_t offset = 0;
   unused << mDoc->SendCaretOffset(mID, &offset);
   return offset;
 }
 
--- a/accessible/ipc/ProxyAccessible.h
+++ b/accessible/ipc/ProxyAccessible.h
@@ -105,16 +105,22 @@ public:
   nsTArray<ProxyAccessible*> RelationByType(RelationType aType) const;
 
   /**
    * Get all relations for this accessible.
    */
   void Relations(nsTArray<RelationType>* aTypes,
                  nsTArray<nsTArray<ProxyAccessible*>>* aTargetSets) const;
 
+  bool IsSearchbox() const;
+
+  nsIAtom* LandmarkRole() const;
+
+  nsIAtom* ARIARoleAtom() const;
+
   int32_t CaretOffset();
   bool SetCaretOffset(int32_t aOffset);
 
   int32_t CharacterCount();
   int32_t SelectionCount();
 
   /**
    * Get the text between the given offsets.
--- a/accessible/mac/mozAccessible.mm
+++ b/accessible/mac/mozAccessible.mm
@@ -887,23 +887,24 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
                                            static_cast<CGFloat>(rect.height) / scaleFactor)];
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 - (NSString*)role
 {
   AccessibleWrap* accWrap = [self getGeckoAccessible];
-  if (!accWrap)
+  if (accWrap) {
+    #ifdef DEBUG_A11Y
+      NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(accWrap),
+                   "Does not support Text when it should");
+    #endif
+  } else if (![self getProxyAccessible]) {
     return nil;
-
-#ifdef DEBUG_A11Y
-  NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(accWrap),
-               "Does not support Text when it should");
-#endif
+  }
 
 #define ROLE(geckoRole, stringRole, atkRole, macRole, msaaRole, ia2Role, nameRule) \
   case roles::geckoRole: \
     return macRole;
 
   switch (mRole) {
 #include "RoleMap.h"
     default:
@@ -912,21 +913,25 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
   }
 
 #undef ROLE
 }
 
 - (NSString*)subrole
 {
   AccessibleWrap* accWrap = [self getGeckoAccessible];
-  if (!accWrap)
-    return nil;
+  ProxyAccessible* proxy = [self getProxyAccessible];
 
   // Deal with landmarks first
-  nsIAtom* landmark = accWrap->LandmarkRole();
+  nsIAtom* landmark = nullptr;
+  if (accWrap)
+    landmark = accWrap->LandmarkRole();
+  else if (proxy)
+    landmark = proxy->LandmarkRole();
+
   if (landmark) {
     if (landmark == nsGkAtoms::application)
       return @"AXLandmarkApplication";
     if (landmark == nsGkAtoms::banner)
       return @"AXLandmarkBanner";
     if (landmark == nsGkAtoms::complementary)
       return @"AXLandmarkComplementary";
     if (landmark == nsGkAtoms::contentinfo)
@@ -939,54 +944,62 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
       return @"AXLandmarkNavigation";
     if (landmark == nsGkAtoms::search)
       return @"AXLandmarkSearch";
     if (landmark == nsGkAtoms::searchbox)
       return @"AXSearchField";
   }
 
   // Now, deal with widget roles
-  if (accWrap->HasARIARole()) {
+  nsIAtom* roleAtom = nullptr;
+  if (accWrap && accWrap->HasARIARole()) {
     nsRoleMapEntry* roleMap = accWrap->ARIARoleMap();
-    if (roleMap->Is(nsGkAtoms::alert))
+    roleAtom = *roleMap->roleAtom;
+  }
+  if (proxy)
+    roleAtom = proxy->ARIARoleAtom();
+
+  if (roleAtom) {
+    if (roleAtom == nsGkAtoms::alert)
       return @"AXApplicationAlert";
-    if (roleMap->Is(nsGkAtoms::alertdialog))
+    if (roleAtom == nsGkAtoms::alertdialog)
       return @"AXApplicationAlertDialog";
-    if (roleMap->Is(nsGkAtoms::article))
+    if (roleAtom == nsGkAtoms::article)
       return @"AXDocumentArticle";
-    if (roleMap->Is(nsGkAtoms::dialog))
+    if (roleAtom == nsGkAtoms::dialog)
       return @"AXApplicationDialog";
-    if (roleMap->Is(nsGkAtoms::document))
+    if (roleAtom == nsGkAtoms::document)
       return @"AXDocument";
-    if (roleMap->Is(nsGkAtoms::log_))
+    if (roleAtom == nsGkAtoms::log_)
       return @"AXApplicationLog";
-    if (roleMap->Is(nsGkAtoms::marquee))
+    if (roleAtom == nsGkAtoms::marquee)
       return @"AXApplicationMarquee";
-    if (roleMap->Is(nsGkAtoms::math))
+    if (roleAtom == nsGkAtoms::math)
       return @"AXDocumentMath";
-    if (roleMap->Is(nsGkAtoms::note_))
+    if (roleAtom == nsGkAtoms::note_)
       return @"AXDocumentNote";
-    if (roleMap->Is(nsGkAtoms::region))
+    if (roleAtom == nsGkAtoms::region)
       return @"AXDocumentRegion";
-    if (roleMap->Is(nsGkAtoms::status))
+    if (roleAtom == nsGkAtoms::status)
       return @"AXApplicationStatus";
-    if (roleMap->Is(nsGkAtoms::tabpanel))
+    if (roleAtom == nsGkAtoms::tabpanel)
       return @"AXTabPanel";
-    if (roleMap->Is(nsGkAtoms::timer))
+    if (roleAtom == nsGkAtoms::timer)
       return @"AXApplicationTimer";
-    if (roleMap->Is(nsGkAtoms::tooltip))
+    if (roleAtom == nsGkAtoms::tooltip)
       return @"AXUserInterfaceTooltip";
   }
 
   switch (mRole) {
     case roles::LIST:
       return @"AXContentList"; // 10.6+ NSAccessibilityContentListSubrole;
 
     case roles::ENTRY:
-      if (accWrap->IsSearchbox())
+      if ((accWrap && accWrap->IsSearchbox()) ||
+          (proxy && proxy->IsSearchbox()))
         return @"AXSearchField";
       break;
 
     case roles::DEFINITION_LIST:
       return @"AXDefinitionList"; // 10.6+ NSAccessibilityDefinitionListSubrole;
 
     case roles::TERM:
       return @"AXTerm";