bug 1151402 - proxy most of IAccessibleText and IAccessibleEditableText
authorTrevor Saunders <tbsaunde@tbsaunde.org>
Mon, 06 Apr 2015 06:04:44 -0400
changeset 238313 e6a2e727bdc43cb37ab5015eae9ad5e25d6745a5
parent 238312 761766b3de865c6007cf530e2598ba6e234fe3ea
child 238314 d34160cac9cd4c29e6b1a85b5857885ae9f993c6
push id58194
push usertrev.saunders@gmail.com
push dateThu, 09 Apr 2015 15:23:13 +0000
treeherdermozilla-inbound@e6a2e727bdc4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1151402
milestone40.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 1151402 - proxy most of IAccessibleText and IAccessibleEditableText r=davidb
accessible/ipc/DocAccessibleChild.cpp
accessible/ipc/DocAccessibleChild.h
accessible/ipc/PDocAccessible.ipdl
accessible/ipc/ProxyAccessible.cpp
accessible/ipc/ProxyAccessible.h
accessible/windows/ProxyWrappers.h
accessible/windows/ia2/ia2Accessible.cpp
accessible/windows/ia2/ia2Accessible.h
accessible/windows/ia2/ia2AccessibleEditableText.cpp
accessible/windows/ia2/ia2AccessibleText.cpp
accessible/windows/ia2/moz.build
accessible/windows/msaa/Platform.cpp
accessible/windows/msaa/moz.build
--- a/accessible/ipc/DocAccessibleChild.cpp
+++ b/accessible/ipc/DocAccessibleChild.cpp
@@ -289,23 +289,24 @@ DocAccessibleChild::RecvSelectionCount(c
   *aCount = acc ? acc->SelectionCount() : 0;
   return true;
 }
 
 bool
 DocAccessibleChild::RecvTextSubstring(const uint64_t& aID,
                                       const int32_t& aStartOffset,
                                       const int32_t& aEndOffset,
-                                      nsString* aText)
+                                      nsString* aText, bool* aValid)
 {
   HyperTextAccessible* acc = IdToHyperTextAccessible(aID);
   if (!acc) {
     return true;
   }
 
+  *aValid = acc->IsValidRange(aStartOffset, aEndOffset);
   acc->TextSubstring(aStartOffset, aEndOffset, *aText);
   return true;
 }
 
 bool
 DocAccessibleChild::RecvGetTextAfterOffset(const uint64_t& aID,
                                            const int32_t& aOffset,
                                            const int32_t& aBoundaryType,
@@ -556,71 +557,75 @@ DocAccessibleChild::RecvReplaceText(cons
   }
 
   return true;
 }
 
 bool
 DocAccessibleChild::RecvInsertText(const uint64_t& aID,
                                    const nsString& aText,
-                                   const int32_t& aPosition)
+                                   const int32_t& aPosition, bool* aValid)
 {
   HyperTextAccessible* acc = IdToHyperTextAccessible(aID);
   if (acc && acc->IsTextRole()) {
+    *aValid = acc->IsValidOffset(aPosition);
     acc->InsertText(aText, aPosition);
   }
 
   return true;
 }
 
 bool
 DocAccessibleChild::RecvCopyText(const uint64_t& aID,
                                  const int32_t& aStartPos,
-                                 const int32_t& aEndPos)
+                                 const int32_t& aEndPos, bool* aValid)
 {
   HyperTextAccessible* acc = IdToHyperTextAccessible(aID);
   if (acc && acc->IsTextRole()) {
     acc->CopyText(aStartPos, aEndPos);
   }
 
   return true;
 }
 
 bool
 DocAccessibleChild::RecvCutText(const uint64_t& aID,
                                 const int32_t& aStartPos,
-                                const int32_t& aEndPos)
+                                const int32_t& aEndPos, bool* aValid)
 {
   HyperTextAccessible* acc = IdToHyperTextAccessible(aID);
   if (acc && acc->IsTextRole()) {
+    *aValid = acc->IsValidRange(aStartPos, aEndPos);
     acc->CutText(aStartPos, aEndPos);
   }
 
   return true;
 }
 
 bool
 DocAccessibleChild::RecvDeleteText(const uint64_t& aID,
                                    const int32_t& aStartPos,
-                                   const int32_t& aEndPos)
+                                   const int32_t& aEndPos, bool* aValid)
 {
   HyperTextAccessible* acc = IdToHyperTextAccessible(aID);
   if (acc && acc->IsTextRole()) {
+    *aValid = acc->IsValidRange(aStartPos, aEndPos);
     acc->DeleteText(aStartPos, aEndPos);
   }
 
   return true;
 }
 
 bool
 DocAccessibleChild::RecvPasteText(const uint64_t& aID,
-                                  const int32_t& aPosition)
+                                  const int32_t& aPosition, bool* aValid)
 {
   HyperTextAccessible* acc = IdToHyperTextAccessible(aID);
   if (acc && acc->IsTextRole()) {
+    *aValid = acc->IsValidOffset(aPosition);
     acc->PasteText(aPosition);
   }
 
   return true;
 }
 
 bool
 DocAccessibleChild::RecvImagePosition(const uint64_t& aID,
--- a/accessible/ipc/DocAccessibleChild.h
+++ b/accessible/ipc/DocAccessibleChild.h
@@ -70,18 +70,18 @@ public:
 
   virtual bool RecvCharacterCount(const uint64_t& aID, int32_t* aCount)
      override;
   virtual bool RecvSelectionCount(const uint64_t& aID, int32_t* aCount)
      override;
 
   virtual bool RecvTextSubstring(const uint64_t& aID,
                                  const int32_t& aStartOffset,
-                                 const int32_t& aEndOffset, nsString* aText)
-    override;
+                                 const int32_t& aEndOffset, nsString* aText,
+                                 bool* aValid) override;
 
   virtual bool RecvGetTextAfterOffset(const uint64_t& aID,
                                       const int32_t& aOffset,
                                       const int32_t& aBoundaryType,
                                       nsString* aText, int32_t* aStartOffset,
                                       int32_t* aEndOffset) override;
   virtual bool RecvGetTextAtOffset(const uint64_t& aID,
                                    const int32_t& aOffset,
@@ -161,32 +161,32 @@ public:
                                           const int32_t& aX,
                                           const int32_t& aY) override;
 
   virtual bool RecvReplaceText(const uint64_t& aID,
                                const nsString& aText) override;
 
   virtual bool RecvInsertText(const uint64_t& aID,
                               const nsString& aText,
-                              const int32_t& aPosition) override;
+                              const int32_t& aPosition, bool* aValid) override;
 
   virtual bool RecvCopyText(const uint64_t& aID,
                             const int32_t& aStartPos,
-                            const int32_t& aEndPos) override;
+                            const int32_t& aEndPos, bool* aValid) override;
 
   virtual bool RecvCutText(const uint64_t& aID,
                            const int32_t& aStartPos,
-                           const int32_t& aEndPos) override;
+                           const int32_t& aEndPos, bool* aValid) override;
 
   virtual bool RecvDeleteText(const uint64_t& aID,
                               const int32_t& aStartPos,
-                              const int32_t& aEndPos) override;
+                              const int32_t& aEndPos, bool* aValid) override;
 
   virtual bool RecvPasteText(const uint64_t& aID,
-                             const int32_t& aPosition) override;
+                             const int32_t& aPosition, bool* aValid) override;
 
   virtual bool RecvImagePosition(const uint64_t& aID,
                                  const uint32_t& aCoordType,
                                  nsIntPoint* aRetVal) override;
 
   virtual bool RecvImageSize(const uint64_t& aID,
                              nsIntSize* aRetVal) override;
 
--- a/accessible/ipc/PDocAccessible.ipdl
+++ b/accessible/ipc/PDocAccessible.ipdl
@@ -77,17 +77,17 @@ child:
   // 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);
   prio(high) sync TextSubstring(uint64_t aID, int32_t aStartOffset, int32_t
-                                aEndOffset) returns(nsString aText);
+                                aEndOffset) returns(nsString aText, bool aValid);
   prio(high) sync GetTextAfterOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
     returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
   prio(high) sync GetTextAtOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
     returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
 
   prio(high) sync GetTextBeforeOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
     returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
   prio(high) sync CharAt(uint64_t aID, int32_t aOffset) returns(uint16_t aChar);
@@ -119,21 +119,26 @@ child:
                     uint32_t aScrollType);
   ScrollSubstringToPoint(uint64_t aID,
                          int32_t aStartOffset,
                          int32_t aEndOffset,
                          uint32_t aCoordinateType,
                          int32_t aX, int32_t aY);
 
   prio(high) sync ReplaceText(uint64_t aID, nsString aText);
-  prio(high) sync InsertText(uint64_t aID, nsString aText, int32_t aPosition);
-  prio(high) sync CopyText(uint64_t aID, int32_t aStartPos, int32_t aEndPos);
-  prio(high) sync CutText(uint64_t aID, int32_t aStartPos, int32_t aEndPos);
-  prio(high) sync DeleteText(uint64_t aID, int32_t aStartPos, int32_t aEndPos);
-  prio(high) sync PasteText(uint64_t aID, int32_t aPosition);
+  prio(high) sync InsertText(uint64_t aID, nsString aText, int32_t aPosition)
+    returns(bool aValid);
+  prio(high) sync CopyText(uint64_t aID, int32_t aStartPos, int32_t aEndPos)
+    returns(bool aValid);
+  prio(high) sync CutText(uint64_t aID, int32_t aStartPos, int32_t aEndPos)
+    returns(bool aValid);
+  prio(high) sync DeleteText(uint64_t aID, int32_t aStartPos, int32_t aEndPos)
+    returns(bool aValid);
+  prio(high) sync PasteText(uint64_t aID, int32_t aPosition)
+    returns(bool aValid);
 
   prio(high) sync ImagePosition(uint64_t aID, uint32_t aCoordType) returns(nsIntPoint aRetVal);
   prio(high) sync ImageSize(uint64_t aID) returns(IntSize aRetVal);
 
   prio(high) sync StartOffset(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
   prio(high) sync EndOffset(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
   prio(high) sync IsLinkValid(uint64_t aID) returns(bool aRetVal);
   prio(high) sync AnchorCount(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
--- a/accessible/ipc/ProxyAccessible.cpp
+++ b/accessible/ipc/ProxyAccessible.cpp
@@ -176,21 +176,23 @@ ProxyAccessible::CharacterCount()
 int32_t
 ProxyAccessible::SelectionCount()
 {
   int32_t count = 0;
   unused << mDoc->SendSelectionCount(mID, &count);
   return count;
 }
 
-void
+bool
 ProxyAccessible::TextSubstring(int32_t aStartOffset, int32_t aEndOfset,
                                nsString& aText) const
 {
-  unused << mDoc->SendTextSubstring(mID, aStartOffset, aEndOfset, &aText);
+  bool valid;
+  unused << mDoc->SendTextSubstring(mID, aStartOffset, aEndOfset, &aText, &valid);
+  return valid;
 }
 
 void
 ProxyAccessible::GetTextAfterOffset(int32_t aOffset,
                                     AccessibleTextBoundary aBoundaryType,
                                     nsString& aText, int32_t* aStartOffset,
                                     int32_t* aEndOffset)
 {
@@ -328,44 +330,54 @@ ProxyAccessible::ScrollSubstringToPoint(
 }
 
 void
 ProxyAccessible::ReplaceText(const nsString& aText)
 {
   unused << mDoc->SendReplaceText(mID, aText);
 }
 
-void
+bool
 ProxyAccessible::InsertText(const nsString& aText, int32_t aPosition)
 {
-  unused << mDoc->SendInsertText(mID, aText, aPosition);
+  bool valid;
+  unused << mDoc->SendInsertText(mID, aText, aPosition, &valid);
+  return valid;
 }
 
-void
+bool
 ProxyAccessible::CopyText(int32_t aStartPos, int32_t aEndPos)
 {
-  unused << mDoc->SendCopyText(mID, aStartPos, aEndPos);
+  bool valid;
+  unused << mDoc->SendCopyText(mID, aStartPos, aEndPos, &valid);
+  return valid;
 }
 
-void
+bool
 ProxyAccessible::CutText(int32_t aStartPos, int32_t aEndPos)
 {
-  unused << mDoc->SendCutText(mID, aStartPos, aEndPos);
+  bool valid;
+  unused << mDoc->SendCutText(mID, aStartPos, aEndPos, &valid);
+  return valid;
 }
 
-void
+bool
 ProxyAccessible::DeleteText(int32_t aStartPos, int32_t aEndPos)
 {
-  unused << mDoc->SendDeleteText(mID, aStartPos, aEndPos);
+  bool valid;
+  unused << mDoc->SendDeleteText(mID, aStartPos, aEndPos, &valid);
+  return valid;
 }
 
-void
+bool
 ProxyAccessible::PasteText(int32_t aPosition)
 {
-  unused << mDoc->SendPasteText(mID, aPosition);
+  bool valid;
+  unused << mDoc->SendPasteText(mID, aPosition, &valid);
+  return valid;
 }
 
 nsIntPoint
 ProxyAccessible::ImagePosition(uint32_t aCoordType)
 {
   nsIntPoint retVal;
   unused << mDoc->SendImagePosition(mID, aCoordType, &retVal);
   return retVal;
--- a/accessible/ipc/ProxyAccessible.h
+++ b/accessible/ipc/ProxyAccessible.h
@@ -109,17 +109,17 @@ public:
   bool SetCaretOffset(int32_t aOffset);
 
   int32_t CharacterCount();
   int32_t SelectionCount();
 
   /**
    * Get the text between the given offsets.
    */
-  void TextSubstring(int32_t aStartOffset, int32_t aEndOfset,
+  bool 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);
 
   void GetTextAtOffset(int32_t aOffset, AccessibleTextBoundary aBoundaryType,
                        nsString& aText, int32_t* aStartOffset,
@@ -164,25 +164,25 @@ public:
 
   void ScrollSubstringToPoint(int32_t aStartOffset,
                               int32_t aEndOffset,
                               uint32_t aCoordinateType,
                               int32_t aX, int32_t aY);
 
   void ReplaceText(const nsString& aText);
 
-  void InsertText(const nsString& aText, int32_t aPosition);
+  bool InsertText(const nsString& aText, int32_t aPosition);
 
-  void CopyText(int32_t aStartPos, int32_t aEndPos);
+  bool CopyText(int32_t aStartPos, int32_t aEndPos);
 
-  void CutText(int32_t aStartPos, int32_t aEndPos);
+  bool CutText(int32_t aStartPos, int32_t aEndPos);
 
-  void DeleteText(int32_t aStartPos, int32_t aEndPos);
+  bool DeleteText(int32_t aStartPos, int32_t aEndPos);
 
-  void PasteText(int32_t aPosition);
+  bool PasteText(int32_t aPosition);
 
   nsIntPoint ImagePosition(uint32_t aCoordType);
 
   nsIntSize ImageSize();
 
   uint32_t StartOffset(bool* aOk);
 
   uint32_t EndOffset(bool* aOk);
copy from accessible/windows/msaa/Platform.cpp
copy to accessible/windows/ProxyWrappers.h
--- a/accessible/windows/msaa/Platform.cpp
+++ b/accessible/windows/ProxyWrappers.h
@@ -1,44 +1,22 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "Platform.h"
-
-#include "AccEvent.h"
-#include "Compatibility.h"
-#include "HyperTextAccessibleWrap.h"
-#include "nsWinUtils.h"
-#include "mozilla/a11y/ProxyAccessible.h"
-
-#include "mozilla/ClearOnShutdown.h"
-
-using namespace mozilla;
-using namespace mozilla::a11y;
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. *
+ */
 
-void
-a11y::PlatformInit()
-{
-  Compatibility::Init();
+#ifndef MOZILLA_A11Y_ProxyWrappers_h
+#define MOZILLA_A11Y_ProxyWrappers_h
 
-  nsWinUtils::MaybeStartWindowEmulation();
-  ClearOnShutdown(&HyperTextAccessibleWrap::sLastTextChangeAcc);
-  ClearOnShutdown(&HyperTextAccessibleWrap::sLastTextChangeString);
-}
+#include "HyperTextAccessible.h"
 
-void
-a11y::PlatformShutdown()
-{
-  ::DestroyCaret();
-
-  nsWinUtils::ShutdownWindowEmulation();
-}
+namespace mozilla {
+namespace a11y {
 
 class ProxyAccessibleWrap : public AccessibleWrap
 {
   public:
   ProxyAccessibleWrap(ProxyAccessible* aProxy) :
     AccessibleWrap(nullptr, nullptr)
   {
     mType = eProxyType;
@@ -46,30 +24,29 @@ class ProxyAccessibleWrap : public Acces
   }
 
   virtual void Shutdown() override
   {
     mBits.proxy = nullptr;
   }
 };
 
-void
-a11y::ProxyCreated(ProxyAccessible* aProxy, uint32_t)
+class HyperTextProxyAccessibleWrap : public ProxyAccessibleWrap,
+                                     public ia2AccessibleEditableText,
+                                     public ia2AccessibleHypertext
 {
-  ProxyAccessibleWrap* wrapper = new ProxyAccessibleWrap(aProxy);
-  wrapper->AddRef();
-  aProxy->SetWrapper(reinterpret_cast<uintptr_t>(wrapper));
+  HyperTextProxyAccessibleWrap(ProxyAccessible* aProxy) :
+    ProxyAccessibleWrap(aProxy) {}
+};
+
+template<typename T>
+inline ProxyAccessible*
+HyperTextProxyFor(T* aWrapper)
+{
+  static_assert(mozilla::IsBaseOf<IUnknown, T>::value, "only IAccessible* should be passed in");
+  auto wrapper = static_cast<HyperTextProxyAccessibleWrap*>(aWrapper);
+  return wrapper->IsProxy() ? wrapper->Proxy() : nullptr;
 }
 
-void
-a11y::ProxyDestroyed(ProxyAccessible* aProxy)
-{
-  ProxyAccessibleWrap* wrapper =
-    reinterpret_cast<ProxyAccessibleWrap*>(aProxy->GetWrapper());
-  wrapper->Shutdown();
-  aProxy->SetWrapper(0);
-  wrapper->Release();
+}
 }
 
-void
-a11y::ProxyEvent(ProxyAccessible*, uint32_t)
-{
-}
+#endif
--- a/accessible/windows/ia2/ia2Accessible.cpp
+++ b/accessible/windows/ia2/ia2Accessible.cpp
@@ -614,32 +614,17 @@ ia2Accessible::get_attributes(BSTR* aAtt
   // characters ":;=,\".
   if (!acc->IsProxy()) {
     nsCOMPtr<nsIPersistentProperties> attributes = acc->Attributes();
     return ConvertToIA2Attributes(attributes, aAttributes);
   }
 
   nsTArray<Attribute> attrs;
   acc->Proxy()->Attributes(&attrs);
-  nsString attrStr;
-  size_t attrCount = attrs.Length();
-  for (size_t i = 0; i < attrCount; i++) {
-    EscapeAttributeChars(attrs[i].Name());
-    EscapeAttributeChars(attrs[i].Value());
-    AppendUTF8toUTF16(attrs[i].Name(), attrStr);
-    attrStr.Append(':');
-    attrStr.Append(attrs[i].Value());
-    attrStr.Append(';');
-  }
-
-  if (attrStr.IsEmpty())
-    return S_FALSE;
-
-  *aAttributes = ::SysAllocStringLen(attrStr.get(), attrStr.Length());
-  return *aAttributes ? S_OK : E_OUTOFMEMORY;
+  return ConvertToIA2Attributes(&attrs, aAttributes);
 
   A11Y_TRYBLOCK_END
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // IAccessible2_2
 
 STDMETHODIMP
@@ -743,16 +728,38 @@ EscapeAttributeChars(String& aStr)
   static const char kCharsToEscape[] = ":;=,\\";
   while ((offset = aStr.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
     aStr.Insert('\\', offset);
     offset += 2;
   }
 }
 
 HRESULT
+ia2Accessible::ConvertToIA2Attributes(nsTArray<Attribute>* aAttributes,
+                                      BSTR* aIA2Attributes)
+{
+  nsString attrStr;
+  size_t attrCount = aAttributes->Length();
+  for (size_t i = 0; i < attrCount; i++) {
+    EscapeAttributeChars(aAttributes->ElementAt(i).Name());
+    EscapeAttributeChars(aAttributes->ElementAt(i).Value());
+    AppendUTF8toUTF16(aAttributes->ElementAt(i).Name(), attrStr);
+    attrStr.Append(':');
+    attrStr.Append(aAttributes->ElementAt(i).Value());
+    attrStr.Append(';');
+  }
+
+  if (attrStr.IsEmpty())
+    return S_FALSE;
+
+  *aIA2Attributes = ::SysAllocStringLen(attrStr.get(), attrStr.Length());
+  return *aIA2Attributes ? S_OK : E_OUTOFMEMORY;
+}
+
+HRESULT
 ia2Accessible::ConvertToIA2Attributes(nsIPersistentProperties* aAttributes,
                                       BSTR* aIA2Attributes)
 {
   *aIA2Attributes = nullptr;
 
   // The format is name:value;name:value; with \ for escaping these
   // characters ":;=,\".
 
--- a/accessible/windows/ia2/ia2Accessible.h
+++ b/accessible/windows/ia2/ia2Accessible.h
@@ -8,16 +8,17 @@
 #define mozilla_a11y_ia2Accessible_h_
 
 #include "nsISupports.h"
 
 #include "Accessible2_2.h"
 
 namespace mozilla {
 namespace a11y {
+class Attribute;
 
 class ia2Accessible : public IAccessible2_2
 {
 public:
 
   // IUnknown
   STDMETHODIMP QueryInterface(REFIID, void**);
 
@@ -101,14 +102,16 @@ public:
     /* [in] */ long maxTargets,
     /* [out, size_is(,*nTargets)] */ IUnknown*** targets,
     /* [out, retval] */ long* nTargets
   );
 
   // Helper method
   static HRESULT ConvertToIA2Attributes(nsIPersistentProperties* aAttributes,
                                         BSTR* aIA2Attributes);
+  static HRESULT ConvertToIA2Attributes(nsTArray<Attribute>* aAttributes,
+                                        BSTR* aIA2Attributes);
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/windows/ia2/ia2AccessibleEditableText.cpp
+++ b/accessible/windows/ia2/ia2AccessibleEditableText.cpp
@@ -5,29 +5,34 @@
  * 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 "ia2AccessibleEditableText.h"
 
 #include "AccessibleEditableText_i.c"
 #include "HyperTextAccessible-inl.h"
 #include "HyperTextAccessibleWrap.h"
+#include "ProxyWrappers.h"
 
 #include "nsCOMPtr.h"
 #include "nsString.h"
 
 using namespace mozilla::a11y;
 
 // IAccessibleEditableText
 
 STDMETHODIMP
 ia2AccessibleEditableText::copyText(long aStartOffset, long aEndOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    return proxy->CopyText(aStartOffset, aEndOffset) ? S_OK : E_INVALIDARG;
+  }
+
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!textAcc->IsValidRange(aStartOffset, aEndOffset))
     return E_INVALIDARG;
 
   textAcc->CopyText(aStartOffset, aEndOffset);
@@ -36,16 +41,20 @@ ia2AccessibleEditableText::copyText(long
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleEditableText::deleteText(long aStartOffset, long aEndOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
+    if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+      return proxy->DeleteText(aStartOffset, aEndOffset) ? S_OK : E_INVALIDARG;
+    }
+
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!textAcc->IsValidRange(aStartOffset, aEndOffset))
     return E_INVALIDARG;
 
   textAcc->DeleteText(aStartOffset, aEndOffset);
@@ -54,37 +63,44 @@ ia2AccessibleEditableText::deleteText(lo
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleEditableText::insertText(long aOffset, BSTR *aText)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  uint32_t length = ::SysStringLen(*aText);
+  nsAutoString text(*aText, length);
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    return proxy->InsertText(text, aOffset) ? S_OK : E_INVALIDARG;
+  }
+
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!textAcc->IsValidOffset(aOffset))
     return E_INVALIDARG;
 
-  uint32_t length = ::SysStringLen(*aText);
-  nsAutoString text(*aText, length);
-
   textAcc->InsertText(text, aOffset);
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleEditableText::cutText(long aStartOffset, long aEndOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    return proxy->CutText(aStartOffset, aEndOffset) ? S_OK : E_INVALIDARG;
+  }
+
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!textAcc->IsValidRange(aStartOffset, aEndOffset))
     return E_INVALIDARG;
 
   textAcc->CutText(aStartOffset, aEndOffset);
@@ -93,16 +109,20 @@ ia2AccessibleEditableText::cutText(long 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleEditableText::pasteText(long aOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    return proxy->PasteText(aOffset) ? S_OK : E_INVALIDARG;
+  }
+
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!textAcc->IsValidOffset(aOffset))
     return E_INVALIDARG;
 
   textAcc->PasteText(aOffset);
--- a/accessible/windows/ia2/ia2AccessibleText.cpp
+++ b/accessible/windows/ia2/ia2AccessibleText.cpp
@@ -7,26 +7,32 @@
 
 #include "ia2AccessibleText.h"
 
 #include "Accessible2.h"
 #include "AccessibleText_i.c"
 
 #include "HyperTextAccessibleWrap.h"
 #include "HyperTextAccessible-inl.h"
+#include "ProxyWrappers.h"
 
 using namespace mozilla::a11y;
 
 // IAccessibleText
 
 STDMETHODIMP
 ia2AccessibleText::addSelection(long aStartOffset, long aEndOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    return proxy->AddToSelection(aStartOffset, aEndOffset) ?
+      S_OK : E_INVALIDARG;
+  }
+
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   return textAcc->AddToSelection(aStartOffset, aEndOffset) ?
     S_OK : E_INVALIDARG;
 
   A11Y_TRYBLOCK_END
@@ -40,26 +46,33 @@ ia2AccessibleText::get_attributes(long a
 
   if (!aStartOffset || !aEndOffset || !aTextAttributes)
     return E_INVALIDARG;
 
   *aStartOffset = 0;
   *aEndOffset = 0;
   *aTextAttributes = nullptr;
 
-  HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
-  if (textAcc->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  int32_t startOffset = 0, endOffset = 0;
+  HRESULT hr;
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    nsAutoTArray<Attribute, 10> attrs;
+    proxy->TextAttributes(true, aOffset, &attrs, &startOffset, &endOffset);
+    hr = AccessibleWrap::ConvertToIA2Attributes(&attrs, aTextAttributes);
+  } else {
+    HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+    if (textAcc->IsDefunct())
+      return CO_E_OBJNOTCONNECTED;
 
-  int32_t startOffset = 0, endOffset = 0;
-  nsCOMPtr<nsIPersistentProperties> attributes =
-    textAcc->TextAttributes(true, aOffset, &startOffset, &endOffset);
+    nsCOMPtr<nsIPersistentProperties> attributes =
+      textAcc->TextAttributes(true, aOffset, &startOffset, &endOffset);
 
-  HRESULT hr = AccessibleWrap::ConvertToIA2Attributes(attributes,
-                                                      aTextAttributes);
+    hr = AccessibleWrap::ConvertToIA2Attributes(attributes, aTextAttributes);
+  }
+
   if (FAILED(hr))
     return hr;
 
   *aStartOffset = startOffset;
   *aEndOffset = endOffset;
 
   return S_OK;
 
@@ -71,21 +84,26 @@ ia2AccessibleText::get_caretOffset(long 
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aOffset)
     return E_INVALIDARG;
 
   *aOffset = -1;
 
-  HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
-  if (textAcc->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    *aOffset = proxy->CaretOffset();
+  } else {
+    HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+    if (textAcc->IsDefunct())
+      return CO_E_OBJNOTCONNECTED;
 
-  *aOffset = textAcc->CaretOffset();
+    *aOffset = textAcc->CaretOffset();
+  }
+
   return *aOffset != -1 ? S_OK : S_FALSE;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_characterExtents(long aOffset,
                                         enum IA2CoordinateType aCoordType,
@@ -93,25 +111,29 @@ ia2AccessibleText::get_characterExtents(
                                         long* aWidth, long* aHeight)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aX || !aY || !aWidth || !aHeight)
     return E_INVALIDARG;
   *aX = *aY = *aWidth = *aHeight = 0;
 
-  HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
-  if (textAcc->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
-
   uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
     nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
     nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
+  nsIntRect rect;
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    rect = proxy->CharBounds(aOffset, geckoCoordType);
+  } else {
+    HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+    if (textAcc->IsDefunct())
+      return CO_E_OBJNOTCONNECTED;
 
-  nsIntRect rect = textAcc->CharBounds(aOffset, geckoCoordType);
+    rect = textAcc->CharBounds(aOffset, geckoCoordType);
+  }
 
   *aX = rect.x;
   *aY = rect.y;
   *aWidth = rect.width;
   *aHeight = rect.height;
   return S_OK;
 
   A11Y_TRYBLOCK_END
@@ -121,68 +143,85 @@ STDMETHODIMP
 ia2AccessibleText::get_nSelections(long* aNSelections)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aNSelections)
     return E_INVALIDARG;
   *aNSelections = 0;
 
-  HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
-  if (textAcc->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    *aNSelections = proxy->SelectionCount();
+  } else {
+    HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+    if (textAcc->IsDefunct())
+      return CO_E_OBJNOTCONNECTED;
 
-  *aNSelections = textAcc->SelectionCount();
+    *aNSelections = textAcc->SelectionCount();
+  }
+
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_offsetAtPoint(long aX, long aY,
                                      enum IA2CoordinateType aCoordType,
                                      long* aOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aOffset)
     return E_INVALIDARG;
   *aOffset = 0;
 
-  HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
-  if (textAcc->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
-
   uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
     nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
     nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
 
-  *aOffset = textAcc->OffsetAtPoint(aX, aY, geckoCoordType);
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    *aOffset = proxy->OffsetAtPoint(aX, aY, geckoCoordType);
+  } else {
+    HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+    if (textAcc->IsDefunct())
+      return CO_E_OBJNOTCONNECTED;
+
+    *aOffset = textAcc->OffsetAtPoint(aX, aY, geckoCoordType);
+  }
+
   return *aOffset == -1 ? S_FALSE : S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_selection(long aSelectionIndex, long* aStartOffset,
                                  long* aEndOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aStartOffset || !aEndOffset)
     return E_INVALIDARG;
   *aStartOffset = *aEndOffset = 0;
 
-  HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
-  if (textAcc->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  int32_t startOffset = 0, endOffset = 0;
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    nsString unused;
+    if (!proxy->SelectionBoundsAt(aSelectionIndex, unused, &startOffset,
+                                  &endOffset))
+      return E_INVALIDARG;
+  } else {
+    HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+    if (textAcc->IsDefunct())
+      return CO_E_OBJNOTCONNECTED;
 
-  int32_t startOffset = 0, endOffset = 0;
-  if (!textAcc->SelectionBoundsAt(aSelectionIndex, &startOffset, &endOffset))
-    return E_INVALIDARG;
+    if (!textAcc->SelectionBoundsAt(aSelectionIndex, &startOffset, &endOffset))
+      return E_INVALIDARG;
+  }
 
   *aStartOffset = startOffset;
   *aEndOffset = endOffset;
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
@@ -191,25 +230,32 @@ ia2AccessibleText::get_text(long aStartO
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aText)
     return E_INVALIDARG;
 
   *aText = nullptr;
 
-  HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
-  if (textAcc->IsDefunct())
-    return CO_E_OBJNOTCONNECTED;
+  nsAutoString text;
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    if (!proxy->TextSubstring(aStartOffset, aEndOffset, text)) {
+      return E_INVALIDARG;
+    }
+  } else {
+    HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
+    if (textAcc->IsDefunct())
+      return CO_E_OBJNOTCONNECTED;
 
-  if (!textAcc->IsValidRange(aStartOffset, aEndOffset))
-    return E_INVALIDARG;
+    if (!textAcc->IsValidRange(aStartOffset, aEndOffset))
+      return E_INVALIDARG;
 
-  nsAutoString text;
-  textAcc->TextSubstring(aStartOffset, aEndOffset, text);
+    textAcc->TextSubstring(aStartOffset, aEndOffset, text);
+  }
+
   if (text.IsEmpty())
     return S_FALSE;
 
   *aText = ::SysAllocStringLen(text.get(), text.Length());
   return *aText ? S_OK : E_OUTOFMEMORY;
 
   A11Y_TRYBLOCK_END
 }
@@ -356,31 +402,39 @@ ia2AccessibleText::get_textAtOffset(long
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::removeSelection(long aSelectionIndex)
 {
   A11Y_TRYBLOCK_BEGIN
 
+    if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+      return proxy->RemoveFromSelection(aSelectionIndex) ? S_OK : E_INVALIDARG;
+    }
+
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   return textAcc->RemoveFromSelection(aSelectionIndex) ?
     S_OK : E_INVALIDARG;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::setCaretOffset(long aOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
+    if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+      return proxy->SetCaretOffset(aOffset) ? S_OK : E_INVALIDARG;
+    }
+
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!textAcc->IsValidOffset(aOffset))
     return E_INVALIDARG;
 
   textAcc->SetCaretOffset(aOffset);
@@ -390,16 +444,21 @@ ia2AccessibleText::setCaretOffset(long a
 }
 
 STDMETHODIMP
 ia2AccessibleText::setSelection(long aSelectionIndex, long aStartOffset,
                                 long aEndOffset)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    return proxy->SetSelectionBoundsAt(aSelectionIndex, aStartOffset,
+                                       aEndOffset) ? S_OK : E_INVALIDARG;
+  }
+
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   return textAcc->SetSelectionBoundsAt(aSelectionIndex, aStartOffset, aEndOffset) ?
     S_OK : E_INVALIDARG;
 
   A11Y_TRYBLOCK_END
@@ -409,32 +468,42 @@ STDMETHODIMP
 ia2AccessibleText::get_nCharacters(long* aNCharacters)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aNCharacters)
     return E_INVALIDARG;
   *aNCharacters = 0;
 
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    *aNCharacters = proxy->CharacterCount();
+    return S_OK;
+  }
+
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   *aNCharacters  = textAcc->CharacterCount();
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex,
                                      enum IA2ScrollType aScrollType)
 {
   A11Y_TRYBLOCK_BEGIN
 
+    if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+      proxy->ScrollSubstringTo(aStartIndex, aEndIndex, aScrollType);
+      return S_OK;
+    }
+
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!textAcc->IsValidRange(aStartIndex, aEndIndex))
     return E_INVALIDARG;
 
   textAcc->ScrollSubstringTo(aStartIndex, aEndIndex, aScrollType);
@@ -445,27 +514,33 @@ ia2AccessibleText::scrollSubstringTo(lon
 
 STDMETHODIMP
 ia2AccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex,
                                           enum IA2CoordinateType aCoordType,
                                           long aX, long aY)
 {
   A11Y_TRYBLOCK_BEGIN
 
+  uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
+    nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
+    nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
+
+  if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
+    proxy->ScrollSubstringToPoint(aStartIndex, aEndIndex, geckoCoordType, aX,
+                                  aY);
+    return S_OK;
+  }
+
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (!textAcc->IsValidRange(aStartIndex, aEndIndex))
     return E_INVALIDARG;
 
-  uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
-    nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
-    nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
-
   textAcc->ScrollSubstringToPoint(aStartIndex, aEndIndex,
                                   geckoCoordType, aX, aY);
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
--- a/accessible/windows/ia2/moz.build
+++ b/accessible/windows/ia2/moz.build
@@ -34,16 +34,17 @@ SOURCES += [
     'ia2AccessibleTable.cpp',
     'ia2AccessibleTableCell.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/accessible/base',
     '/accessible/generic',
     '/accessible/html',
+    '/accessible/windows',
     '/accessible/windows/msaa',
     '/accessible/xpcom',
     '/accessible/xul',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 # The midl generated code include Windows headers which defines min and max
--- a/accessible/windows/msaa/Platform.cpp
+++ b/accessible/windows/msaa/Platform.cpp
@@ -6,16 +6,17 @@
 
 #include "Platform.h"
 
 #include "AccEvent.h"
 #include "Compatibility.h"
 #include "HyperTextAccessibleWrap.h"
 #include "nsWinUtils.h"
 #include "mozilla/a11y/ProxyAccessible.h"
+#include "ProxyWrappers.h"
 
 #include "mozilla/ClearOnShutdown.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 void
 a11y::PlatformInit()
@@ -30,32 +31,16 @@ a11y::PlatformInit()
 void
 a11y::PlatformShutdown()
 {
   ::DestroyCaret();
 
   nsWinUtils::ShutdownWindowEmulation();
 }
 
-class ProxyAccessibleWrap : public AccessibleWrap
-{
-  public:
-  ProxyAccessibleWrap(ProxyAccessible* aProxy) :
-    AccessibleWrap(nullptr, nullptr)
-  {
-    mType = eProxyType;
-    mBits.proxy = aProxy;
-  }
-
-  virtual void Shutdown() override
-  {
-    mBits.proxy = nullptr;
-  }
-};
-
 void
 a11y::ProxyCreated(ProxyAccessible* aProxy, uint32_t)
 {
   ProxyAccessibleWrap* wrapper = new ProxyAccessibleWrap(aProxy);
   wrapper->AddRef();
   aProxy->SetWrapper(reinterpret_cast<uintptr_t>(wrapper));
 }
 
--- a/accessible/windows/msaa/moz.build
+++ b/accessible/windows/msaa/moz.build
@@ -43,16 +43,17 @@ if CONFIG['MOZ_XUL']:
         'XULMenuAccessibleWrap.cpp',
         'XULTreeGridAccessibleWrap.cpp',
     ]
 
 LOCAL_INCLUDES += [
     '/accessible/base',
     '/accessible/generic',
     '/accessible/html',
+    '/accessible/windows',
     '/accessible/windows/ia2',
     '/accessible/windows/sdn',
     '/accessible/windows/uia',
     '/accessible/xpcom',
     '/accessible/xul',
     '/dom/base',
 ]