bug 1119923 - allow proxies to implement non standard interfaces r=davidb
authorTrevor Saunders <trev.saunders@gmail.com>
Fri, 09 Jan 2015 15:01:39 -0500
changeset 252648 5b5517af41232739241566feb3aa17fdee2f3812
parent 252647 4f99aee889fa0cff3b4d1ca6ff6c21c1f1ead64f
child 252649 ae6a30f691eec73b943026d942bb261cf5da6254
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
bugs1119923
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 1119923 - allow proxies to implement non standard interfaces r=davidb
accessible/atk/AccessibleWrap.cpp
accessible/atk/nsMaiInterfaceText.cpp
accessible/base/DocManager.cpp
accessible/base/Platform.h
accessible/ipc/DocAccessibleChild.cpp
accessible/ipc/DocAccessibleChild.h
accessible/ipc/DocAccessibleParent.cpp
accessible/ipc/PDocAccessible.ipdl
accessible/ipc/ProxyAccessible.cpp
accessible/ipc/ProxyAccessible.h
accessible/mac/Platform.mm
accessible/other/Platform.cpp
accessible/windows/msaa/Platform.cpp
--- a/accessible/atk/AccessibleWrap.cpp
+++ b/accessible/atk/AccessibleWrap.cpp
@@ -1014,25 +1014,30 @@ GetProxy(AtkObject* aObj)
 
 AtkObject*
 GetWrapperFor(ProxyAccessible* aProxy)
 {
   return reinterpret_cast<AtkObject*>(aProxy->GetWrapper() & ~IS_PROXY);
 }
 
 static uint16_t
-GetInterfacesForProxy(ProxyAccessible* aProxy)
+GetInterfacesForProxy(ProxyAccessible* aProxy, uint32_t aInterfaces)
 {
-  return MAI_INTERFACE_COMPONENT;
+  uint16_t interfaces = 1 << MAI_INTERFACE_COMPONENT;
+  if (aInterfaces & Interfaces::HYPERTEXT)
+    interfaces |= (1 << MAI_INTERFACE_HYPERTEXT) | (1 << MAI_INTERFACE_TEXT)
+        | (1 << MAI_INTERFACE_EDITABLE_TEXT);
+
+  return interfaces;
 }
 
 void
-a11y::ProxyCreated(ProxyAccessible* aProxy)
+a11y::ProxyCreated(ProxyAccessible* aProxy, uint32_t aInterfaces)
 {
-  GType type = GetMaiAtkType(GetInterfacesForProxy(aProxy));
+  GType type = GetMaiAtkType(GetInterfacesForProxy(aProxy, aInterfaces));
   NS_ASSERTION(type, "why don't we have a type!");
 
   AtkObject* obj =
     reinterpret_cast<AtkObject *>
     (g_object_new(type, nullptr));
   if (!obj)
     return;
 
--- a/accessible/atk/nsMaiInterfaceText.cpp
+++ b/accessible/atk/nsMaiInterfaceText.cpp
@@ -4,16 +4,17 @@
  * 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 "InterfaceInitFuncs.h"
 
 #include "Accessible-inl.h"
 #include "HyperTextAccessible-inl.h"
 #include "nsMai.h"
+#include "ProxyAccessible.h"
 
 #include "nsIAccessibleTypes.h"
 #include "nsIPersistentProperties2.h"
 #include "nsISimpleEnumerator.h"
 
 #include "mozilla/Likely.h"
 
 using namespace mozilla;
@@ -105,31 +106,33 @@ ConvertTexttoAsterisks(AccessibleWrap* a
 }
 
 extern "C" {
 
 static gchar*
 getTextCB(AtkText *aText, gint aStartOffset, gint aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return nullptr;
+  nsAutoString autoStr;
+  if (accWrap) {
+    HyperTextAccessible* text = accWrap->AsHyperText();
+    if (!text || !text->IsTextRole())
+      return nullptr;
 
-  HyperTextAccessible* text = accWrap->AsHyperText();
-  if (!text || !text->IsTextRole())
-    return nullptr;
-
-    nsAutoString autoStr;
     text->TextSubstring(aStartOffset, aEndOffset, autoStr);
 
     ConvertTexttoAsterisks(accWrap, autoStr);
-    NS_ConvertUTF16toUTF8 cautoStr(autoStr);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    proxy->TextSubstring(aStartOffset, aEndOffset, autoStr);
+  }
 
-    //copy and return, libspi will free it.
-    return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
+  NS_ConvertUTF16toUTF8 cautoStr(autoStr);
+
+  //copy and return, libspi will free it.
+  return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
 }
 
 static gchar*
 getTextAfterOffsetCB(AtkText *aText, gint aOffset,
                      AtkTextBoundary aBoundaryType,
                      gint *aStartOffset, gint *aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
--- a/accessible/base/DocManager.cpp
+++ b/accessible/base/DocManager.cpp
@@ -544,10 +544,10 @@ DocManager::RemoteDocAdded(DocAccessible
   if (!sRemoteDocuments) {
     sRemoteDocuments = new nsTArray<DocAccessibleParent*>;
     ClearOnShutdown(&sRemoteDocuments);
   }
 
   MOZ_ASSERT(!sRemoteDocuments->Contains(aDoc),
       "How did we already have the doc!");
   sRemoteDocuments->AppendElement(aDoc);
-  ProxyCreated(aDoc);
+  ProxyCreated(aDoc, 0);
 }
--- a/accessible/base/Platform.h
+++ b/accessible/base/Platform.h
@@ -50,17 +50,17 @@ void PlatformInit();
  * Note this is called before internal accessibility support is shutdown.
  */
 void PlatformShutdown();
 
 /**
  * called when a new ProxyAccessible is created, so the platform may setup a
  * wrapper for it, or take other action.
  */
-void ProxyCreated(ProxyAccessible*);
+void ProxyCreated(ProxyAccessible* aProxy, uint32_t aInterfaces);
 
 /**
  * Called just before a ProxyAccessible is destroyed so its wrapper can be
  * disposed of and other action taken.
  */
 void ProxyDestroyed(ProxyAccessible*);
 
 /**
--- a/accessible/ipc/DocAccessibleChild.cpp
+++ b/accessible/ipc/DocAccessibleChild.cpp
@@ -2,37 +2,49 @@
 /* vim: set ts=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/. */
 
 #include "DocAccessibleChild.h"
 
 #include "Accessible-inl.h"
+#include "ProxyAccessible.h"
 
 #include "nsIPersistentProperties2.h"
 #include "nsISimpleEnumerator.h"
 
 namespace mozilla {
 namespace a11y {
 
-void
+static uint32_t
+InterfacesFor(Accessible* aAcc)
+{
+  uint32_t interfaces = 0;
+  if (aAcc->IsHyperText() && aAcc->AsHyperText()->IsTextRole())
+    interfaces |= Interfaces::HYPERTEXT;
+
+  return interfaces;
+}
+
+static void
 SerializeTree(Accessible* aRoot, nsTArray<AccessibleData>& aTree)
 {
   uint64_t id = reinterpret_cast<uint64_t>(aRoot->UniqueID());
   uint32_t role = aRoot->Role();
   uint32_t childCount = aRoot->ChildCount();
+  uint32_t interfaces = InterfacesFor(aRoot);
 
   // OuterDocAccessibles are special because we don't want to serialize the
   // child doc here, we'll call PDocAccessibleConstructor in
   // NotificationController.
   if (childCount == 1 && aRoot->GetChildAt(0)->IsDoc())
     childCount = 0;
 
-  aTree.AppendElement(AccessibleData(id, role, childCount));
+  aTree.AppendElement(AccessibleData(id, role, childCount, interfaces));
   for (uint32_t i = 0; i < childCount; i++)
     SerializeTree(aRoot->GetChildAt(i), aTree);
 }
 
 void
 DocAccessibleChild::ShowEvent(AccShowEvent* aShowEvent)
 {
   Accessible* parent = aShowEvent->Parent();
@@ -112,10 +124,24 @@ DocAccessibleChild::RecvAttributes(const
     rv = propElem->GetValue(value);
     NS_ENSURE_SUCCESS(rv, false);
 
     aAttributes->AppendElement(Attribute(name, value));
     }
 
   return true;
 }
+
+bool
+DocAccessibleChild::RecvTextSubstring(const uint64_t& aID,
+                                      const int32_t& aStartOffset,
+                                      const int32_t& aEndOffset,
+                                      nsString* aText)
+{
+  Accessible* acc = mDoc->GetAccessibleByUniqueID((void*)aID);
+  if (!acc || !acc->IsHyperText())
+    return false;
+
+  acc->AsHyperText()->TextSubstring(aStartOffset, aEndOffset, *aText);
+  return true;
 }
 }
+}
--- a/accessible/ipc/DocAccessibleChild.h
+++ b/accessible/ipc/DocAccessibleChild.h
@@ -44,16 +44,20 @@ public:
   virtual bool RecvName(const uint64_t& aID, nsString* aName) MOZ_OVERRIDE;
 
   /*
    * Get the description for the accessible with given id.
    */
   virtual bool RecvDescription(const uint64_t& aID, nsString* aDesc) 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;
 
 private:
   DocAccessible* mDoc;
 };
 
 }
 }
 
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=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/. */
 
 #include "DocAccessibleParent.h"
 #include "nsAutoPtr.h"
 #include "mozilla/a11y/Platform.h"
+#include "ProxyAccessible.h"
 
 namespace mozilla {
 namespace a11y {
 
 bool
 DocAccessibleParent::RecvShowEvent(const ShowEventData& aData)
 {
   if (aData.NewTree().IsEmpty()) {
@@ -69,17 +70,17 @@ DocAccessibleParent::AddSubtree(ProxyAcc
     return 0;
   }
 
   auto role = static_cast<a11y::role>(newChild.Role());
   ProxyAccessible* newProxy =
     new ProxyAccessible(newChild.ID(), aParent, this, role);
   aParent->AddChildAt(aIdxInParent, newProxy);
   mAccessibles.PutEntry(newChild.ID())->mProxy = newProxy;
-  ProxyCreated(newProxy);
+  ProxyCreated(newProxy, newChild.Interfaces());
 
   uint32_t accessibles = 1;
   uint32_t kids = newChild.ChildrenCount();
   for (uint32_t i = 0; i < kids; i++) {
     uint32_t consumed = AddSubtree(newProxy, aNewTree, aIdx + accessibles, i);
     if (!consumed)
       return 0;
 
@@ -137,17 +138,17 @@ DocAccessibleParent::AddChildDoc(DocAcce
   ProxyAccessible* outerDoc = mAccessibles.GetEntry(aParentID)->mProxy;
   if (!outerDoc)
     return false;
 
   aChildDoc->mParent = outerDoc;
   outerDoc->SetChildDoc(aChildDoc);
   mChildDocs.AppendElement(aChildDoc);
   aChildDoc->mParentDoc = this;
-  ProxyCreated(aChildDoc);
+  ProxyCreated(aChildDoc, 0);
   return true;
 }
 
 PLDHashOperator
 DocAccessibleParent::ShutdownAccessibles(ProxyEntry* entry, void*)
 {
   ProxyDestroyed(entry->mProxy);
   return PL_DHASH_NEXT;
--- a/accessible/ipc/PDocAccessible.ipdl
+++ b/accessible/ipc/PDocAccessible.ipdl
@@ -9,16 +9,17 @@ include protocol PContent;
 namespace mozilla {
 namespace a11y {
 
 struct AccessibleData
 {
   uint64_t ID;
   uint32_t Role;
   uint32_t ChildrenCount;
+  uint32_t Interfaces;
 };
 
 struct ShowEventData
 {
   uint64_t ID;
   uint32_t Idx;
   AccessibleData[] NewTree;
 };
@@ -44,12 +45,14 @@ parent:
   ShowEvent(ShowEventData data);
   HideEvent(uint64_t aRootID);
 
 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 Description(uint64_t aID) returns(nsString desc);
   prio(high) sync Attributes(uint64_t aID) returns(Attribute[] attributes);
+prio(high) sync TextSubstring(uint64_t aID, int32_t aStartOffset, int32_t
+                              aEndOffset) returns(nsString aText);
 };
 
 }
 }
--- a/accessible/ipc/ProxyAccessible.cpp
+++ b/accessible/ipc/ProxyAccessible.cpp
@@ -64,10 +64,17 @@ ProxyAccessible::Description(nsString& a
   unused << mDoc->SendDescription(mID, &aDesc);
 }
 
 void
 ProxyAccessible::Attributes(nsTArray<Attribute> *aAttrs) const
 {
   unused << mDoc->SendAttributes(mID, aAttrs);
 }
+
+void
+ProxyAccessible::TextSubstring(int32_t aStartOffset, int32_t aEndOfset,
+                               nsString& aText) const
+{
+  unused << mDoc->SendTextSubstring(mID, aStartOffset, aEndOfset, &aText);
 }
 }
+}
--- a/accessible/ipc/ProxyAccessible.h
+++ b/accessible/ipc/ProxyAccessible.h
@@ -75,16 +75,22 @@ public:
   void Description(nsString& aDesc) const;
 
   /**
    * Get the set of attributes on the proxied accessible.
    */
   void Attributes(nsTArray<Attribute> *aAttrs) const;
 
   /**
+   * Get the text between the given offsets.
+   */
+  void TextSubstring(int32_t aStartOffset, int32_t aEndOfset,
+                     nsString& aText) const;
+
+  /**
    * Allow the platform to store a pointers worth of data on us.
    */
   uintptr_t GetWrapper() const { return mWrapper; }
   void SetWrapper(uintptr_t aWrapper) { mWrapper = aWrapper; }
 
   /*
    * Return the ID of the accessible being proxied.
    */
@@ -103,12 +109,17 @@ private:
   nsTArray<ProxyAccessible*> mChildren;
   DocAccessibleParent* mDoc;
   uintptr_t mWrapper;
   uint64_t mID;
   role mRole : 31;
   bool mOuterDoc : 1;
 };
 
+enum Interfaces
+{
+  HYPERTEXT = 1
+};
+
 }
 }
 
 #endif
--- a/accessible/mac/Platform.mm
+++ b/accessible/mac/Platform.mm
@@ -29,17 +29,17 @@ PlatformInit()
 }
 
 void
 PlatformShutdown()
 {
 }
 
 void
-ProxyCreated(ProxyAccessible*)
+ProxyCreated(ProxyAccessible*, uint32_t)
 {
 }
 
 void
 ProxyDestroyed(ProxyAccessible*)
 {
 }
 
--- a/accessible/other/Platform.cpp
+++ b/accessible/other/Platform.cpp
@@ -15,17 +15,17 @@ a11y::PlatformInit()
 }
 
 void
 a11y::PlatformShutdown()
 {
 }
 
 void
-a11y::ProxyCreated(ProxyAccessible*)
+a11y::ProxyCreated(ProxyAccessible*, uint32_t)
 {
 }
 
 void
 a11y::ProxyDestroyed(ProxyAccessible*)
 {
 }
 
--- a/accessible/windows/msaa/Platform.cpp
+++ b/accessible/windows/msaa/Platform.cpp
@@ -30,17 +30,17 @@ void
 a11y::PlatformShutdown()
 {
   ::DestroyCaret();
 
   nsWinUtils::ShutdownWindowEmulation();
 }
 
 void
-a11y::ProxyCreated(ProxyAccessible*)
+a11y::ProxyCreated(ProxyAccessible*, uint32_t)
 {
 }
 
 void
 a11y::ProxyDestroyed(ProxyAccessible*)
 {
 }