Bug 1479039 - Extend BatchData struct and added focus path cache. r=yzen a=jcristau
authorEitan Isaacson <eitan@monotonous.org>
Mon, 12 Nov 2018 16:41:38 +0000
changeset 501349 f5d4bc87f0fd88b769b19da3e843e404d877dbc3
parent 501348 e3c4ebd80791657a3ee5523b5a56aebe45936446
child 501350 44d90df54ca9c09561577f8ede75c24d78935337
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersyzen, jcristau
bugs1479039
milestone64.0
Bug 1479039 - Extend BatchData struct and added focus path cache. r=yzen a=jcristau Differential Revision: https://phabricator.services.mozilla.com/D11214
accessible/android/AccessibleWrap.cpp
accessible/android/AccessibleWrap.h
accessible/android/DocAccessibleWrap.cpp
accessible/android/DocAccessibleWrap.h
accessible/android/Platform.cpp
accessible/android/ProxyAccessibleWrap.h
accessible/ipc/other/PDocAccessible.ipdl
--- a/accessible/android/AccessibleWrap.cpp
+++ b/accessible/android/AccessibleWrap.cpp
@@ -41,33 +41,54 @@ AccessibleWrap::AccessibleWrap(nsIConten
 //-----------------------------------------------------
 // destruction
 //-----------------------------------------------------
 AccessibleWrap::~AccessibleWrap() {}
 
 nsresult
 AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
 {
+  auto accessible = static_cast<AccessibleWrap*>(aEvent->GetAccessible());
+  NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE);
+  DocAccessibleWrap* doc = static_cast<DocAccessibleWrap*>(accessible->Document());
+  if (doc) {
+    switch (aEvent->GetEventType()) {
+      case nsIAccessibleEvent::EVENT_FOCUS: {
+        if (DocAccessibleWrap* topContentDoc = doc->GetTopLevelContentDoc(accessible)) {
+          topContentDoc->CacheFocusPath(accessible);
+        }
+        break;
+      }
+      case nsIAccessibleEvent::EVENT_VIRTUALCURSOR_CHANGED: {
+        AccVCChangeEvent* vcEvent = downcast_accEvent(aEvent);
+        auto newPosition = static_cast<AccessibleWrap*>(vcEvent->NewAccessible());
+        if (newPosition) {
+          if (DocAccessibleWrap* topContentDoc = doc->GetTopLevelContentDoc(accessible)) {
+            topContentDoc->CacheFocusPath(newPosition);
+          }
+        }
+        break;
+      }
+    }
+  }
+
   nsresult rv = Accessible::HandleAccEvent(aEvent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (IPCAccessibilityActive()) {
     return NS_OK;
   }
 
-  auto accessible = static_cast<AccessibleWrap*>(aEvent->GetAccessible());
-  NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE);
-
   // The accessible can become defunct if we have an xpcom event listener
   // which decides it would be fun to change the DOM and flush layout.
   if (accessible->IsDefunct() || !accessible->IsBoundToParent()) {
     return NS_OK;
   }
 
-  if (DocAccessible* doc = accessible->Document()) {
+  if (doc) {
     if (!nsCoreUtils::IsContentDocument(doc->DocumentNode())) {
       return NS_OK;
     }
   }
 
   SessionAccessibility* sessionAcc =
     SessionAccessibility::GetInstanceFor(accessible);
   if (!sessionAcc) {
--- a/accessible/android/AccessibleWrap.h
+++ b/accessible/android/AccessibleWrap.h
@@ -43,16 +43,18 @@ public:
                                                 const double& aMaxVal,
                                                 const double& aStep,
                                                 nsIPersistentProperties* aAttributes);
 
   mozilla::java::GeckoBundle::LocalRef ToSmallBundle(const uint64_t aState, const nsIntRect& aBounds);
 
   mozilla::java::GeckoBundle::LocalRef ToSmallBundle();
 
+  virtual void WrapperDOMNodeID(nsString& aDOMNodeID);
+
   int32_t AndroidClass()
   {
     return mID == kNoID ? java::SessionAccessibility::CLASSNAME_WEBVIEW
                         : GetAndroidClass(WrapperRole());
   }
 
   static already_AddRefed<nsIPersistentProperties> AttributeArrayToProperties(
     const nsTArray<Attribute>& aAttributes);
@@ -73,18 +75,16 @@ protected:
 
 private:
   virtual AccessibleWrap* WrapperParent() { return static_cast<AccessibleWrap*>(Parent()); }
 
   virtual bool WrapperRangeInfo(double* aCurVal, double* aMinVal, double* aMaxVal, double* aStep);
 
   virtual role WrapperRole() { return Role(); }
 
-  virtual void WrapperDOMNodeID(nsString& aDOMNodeID);
-
   static void GetRoleDescription(role aRole,
                                  nsAString& aGeckoRole,
                                  nsAString& aRoleDescription);
   static uint32_t GetFlags(role aRole, uint64_t aState);
 };
 
 static inline AccessibleWrap*
 WrapperFor(const ProxyAccessible* aProxy)
--- a/accessible/android/DocAccessibleWrap.cpp
+++ b/accessible/android/DocAccessibleWrap.cpp
@@ -4,16 +4,18 @@
  * 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 "DocAccessibleWrap.h"
 #include "nsIDocShell.h"
 #include "nsLayoutUtils.h"
 #include "DocAccessibleChild.h"
 #include "nsAccessibilityService.h"
+#include "nsAccUtils.h"
+#include "nsIPersistentProperties2.h"
 #include "SessionAccessibility.h"
 
 using namespace mozilla::a11y;
 
 const uint32_t kCacheRefreshInterval = 500;
 
 ////////////////////////////////////////////////////////////////////////////////
 // DocAccessibleWrap
@@ -133,17 +135,25 @@ DocAccessibleWrap::CacheViewportCallback
     nsTArray<BatchData> cacheData(inViewAccs.Count());
     for (auto iter = inViewAccs.Iter(); !iter.Done(); iter.Next()) {
       Accessible* accessible = iter.Data();
       auto uid = accessible->IsDoc() && accessible->AsDoc()->IPCDoc() ? 0
         : reinterpret_cast<uint64_t>(accessible->UniqueID());
       cacheData.AppendElement(BatchData(accessible->Document()->IPCDoc(),
                                         uid,
                                         accessible->State(),
-                                        accessible->Bounds()));
+                                        accessible->Bounds(),
+                                        nsString(),
+                                        nsString(),
+                                        nsString(),
+                                        UnspecifiedNaN<double>(),
+                                        UnspecifiedNaN<double>(),
+                                        UnspecifiedNaN<double>(),
+                                        UnspecifiedNaN<double>(),
+                                        nsTArray<Attribute>()));
     }
 
     ipcDoc->SendBatch(eBatch_Viewport, cacheData);
   } else if (SessionAccessibility* sessionAcc = SessionAccessibility::GetInstanceFor(docAcc)) {
     nsTArray<AccessibleWrap*> accessibles(inViewAccs.Count());
     for (auto iter = inViewAccs.Iter(); !iter.Done(); iter.Next()) {
       accessibles.AppendElement(static_cast<AccessibleWrap*>(iter.Data().get()));
     }
@@ -166,8 +176,57 @@ DocAccessibleWrap::CacheViewport()
                                 kCacheRefreshInterval,
                                 nsITimer::TYPE_ONE_SHOT,
                                 "a11y::DocAccessibleWrap::CacheViewport");
     if (mCacheRefreshTimer) {
       NS_ADDREF_THIS(); // Kung fu death grip
     }
   }
 }
+
+DocAccessibleWrap*
+DocAccessibleWrap::GetTopLevelContentDoc(AccessibleWrap* aAccessible) {
+  DocAccessibleWrap* doc = static_cast<DocAccessibleWrap*>(aAccessible->Document());
+  while (doc && doc->VirtualViewID() != kNoID) {
+    doc = static_cast<DocAccessibleWrap*>(doc->ParentDocument());
+  }
+
+  return doc;
+}
+
+void
+DocAccessibleWrap::CacheFocusPath(AccessibleWrap* aAccessible)
+{
+  if (IPCAccessibilityActive()) {
+    DocAccessibleChild* ipcDoc = IPCDoc();
+    nsTArray<BatchData> cacheData;
+    for (AccessibleWrap* acc = aAccessible; acc && acc != this->Parent();
+         acc = static_cast<AccessibleWrap*>(acc->Parent())) {
+      auto uid = acc->IsDoc() && acc->AsDoc()->IPCDoc() ? 0
+        : reinterpret_cast<uint64_t>(acc->UniqueID());
+      nsAutoString name;
+      acc->Name(name);
+      nsAutoString textValue;
+      acc->Value(textValue);
+      nsAutoString nodeID;
+      acc->WrapperDOMNodeID(nodeID);
+      nsCOMPtr<nsIPersistentProperties> props = acc->Attributes();
+      nsTArray<Attribute> attributes;
+      nsAccUtils::PersistentPropertiesToArray(props, &attributes);
+      cacheData.AppendElement(BatchData(acc->Document()->IPCDoc(),
+                                        uid,
+                                        acc->State(),
+                                        acc->Bounds(),
+                                        name,
+                                        textValue,
+                                        nodeID,
+                                        acc->CurValue(),
+                                        acc->MinValue(),
+                                        acc->MaxValue(),
+                                        acc->Step(),
+                                        attributes));
+    }
+
+    ipcDoc->SendBatch(eBatch_FocusPath, cacheData);
+  } else {
+    // XXX: Local codepath, next patch
+  }
+}
\ No newline at end of file
--- a/accessible/android/DocAccessibleWrap.h
+++ b/accessible/android/DocAccessibleWrap.h
@@ -25,18 +25,23 @@ public:
    */
   void AddID(uint32_t aID, AccessibleWrap* aAcc)
   {
     mIDToAccessibleMap.Put(aID, aAcc);
   }
   void RemoveID(uint32_t aID) { mIDToAccessibleMap.Remove(aID); }
   AccessibleWrap* GetAccessibleByID(int32_t aID) const;
 
+  DocAccessibleWrap* GetTopLevelContentDoc(AccessibleWrap* aAccessible);
+
+  void CacheFocusPath(AccessibleWrap* aAccessible);
+
   enum {
-    eBatch_Viewport = 0
+    eBatch_Viewport = 0,
+    eBatch_FocusPath = 1,
   };
 
 protected:
   /*
    * This provides a mapping from 32 bit id to accessible objects.
    */
   nsDataHashtable<nsUint32HashKey, AccessibleWrap*> mIDToAccessibleMap;
 
--- a/accessible/android/Platform.cpp
+++ b/accessible/android/Platform.cpp
@@ -216,13 +216,16 @@ a11y::ProxyBatch(ProxyAccessible* aDocum
   for (size_t i = 0; i < aAccessibles.Length(); i++) {
     accWraps.AppendElement(WrapperFor(aAccessibles.ElementAt(i)));
   }
 
   switch (aBatchType) {
     case DocAccessibleWrap::eBatch_Viewport:
       sessionAcc->ReplaceViewportCache(accWraps, aData);
       break;
+    case DocAccessibleWrap::eBatch_FocusPath:
+      // XXX: Next patch
+      break;
     default:
       MOZ_ASSERT_UNREACHABLE("Unknown batch type.");
       break;
   }
 }
--- a/accessible/android/ProxyAccessibleWrap.h
+++ b/accessible/android/ProxyAccessibleWrap.h
@@ -49,25 +49,24 @@ public:
   // AccessibleWrap
 
   virtual void SetTextContents(const nsAString& aText) override;
 
   virtual void GetTextContents(nsAString& aText) override;
 
   virtual bool GetSelectionBounds(int32_t* aStartOffset, int32_t* aEndOffset) override;
 
+  virtual void WrapperDOMNodeID(nsString& aDOMNodeID) override;
+
 private:
   virtual role WrapperRole() override;
 
   virtual AccessibleWrap* WrapperParent() override;
 
   virtual bool WrapperRangeInfo(double* aCurVal, double* aMinVal, double* aMaxVal, double* aStep) override;
-
-  virtual void WrapperDOMNodeID(nsString& aDOMNodeID) override;
-
 };
 
 class DocProxyAccessibleWrap : public ProxyAccessibleWrap
 {
 public:
   explicit DocProxyAccessibleWrap(DocAccessibleParent* aProxy)
     : ProxyAccessibleWrap(aProxy)
   {
--- a/accessible/ipc/other/PDocAccessible.ipdl
+++ b/accessible/ipc/other/PDocAccessible.ipdl
@@ -31,16 +31,24 @@ union OriginDocument
 };
 
 struct BatchData
 {
   OriginDocument Document;
   uint64_t ID;
   uint64_t State;
   nsIntRect Bounds;
+  nsString Name;
+  nsString TextValue;
+  nsString DOMNodeID;
+  double CurValue;
+  double MinValue;
+  double MaxValue;
+  double Step;
+  Attribute[] Attributes;
 };
 
 struct ShowEventData
 {
   uint64_t ID;
   uint32_t Idx;
   AccessibleData[] NewTree;
   bool EventSuppressed;