Bug 1402951 - No show events for content on document load complete. r=aklotz, r=yzen, a=ritu
authorAlexander Surkov <surkov.alexander@gmail.com>
Tue, 03 Oct 2017 10:58:27 -0400
changeset 434635 ca2f2ff689cc282c77f3a5d7f9725be7273519e2
parent 434634 4566eb0d57603d7958c28baf70a2b48bd65620c1
child 434636 21e3f04ae989fd57b7a4acfa948e8587784dcf4b
push id1567
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 12:36:05 +0000
treeherdermozilla-release@e512c14a0406 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaklotz, yzen, ritu
bugs1402951
milestone57.0
Bug 1402951 - No show events for content on document load complete. r=aklotz, r=yzen, a=ritu
accessible/generic/DocAccessible.cpp
accessible/ipc/DocAccessibleChildBase.cpp
accessible/ipc/DocAccessibleChildBase.h
accessible/ipc/DocAccessibleParent.cpp
accessible/ipc/other/PDocAccessible.ipdl
accessible/ipc/win/DocAccessibleChild.h
accessible/ipc/win/PDocAccessible.ipdl
accessible/tests/mochitest/treeupdate/test_ariaowns.html
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -1531,23 +1531,25 @@ DocAccessible::DoInitialUpdate()
   // this reorder event is processed by parent document then events targeted to
   // this document may be fired prior to this reorder event. If this is
   // a problem then consider to keep event processing per tab document.
   if (!IsRoot()) {
     RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(Parent());
     ParentDocument()->FireDelayedEvent(reorderEvent);
   }
 
-  TreeMutation mt(this);
-  uint32_t childCount = ChildCount();
-  for (uint32_t i = 0; i < childCount; i++) {
-    Accessible* child = GetChildAt(i);
-    mt.AfterInsertion(child);
+  if (IPCAccessibilityActive()) {
+    DocAccessibleChild* ipcDoc = IPCDoc();
+    MOZ_ASSERT(ipcDoc);
+    if (ipcDoc) {
+      for (auto idx = 0U; idx < mChildren.Length(); idx++) {
+        ipcDoc->InsertIntoIpcTree(this, mChildren.ElementAt(idx), idx);
+      }
+    }
   }
-  mt.Done();
 }
 
 void
 DocAccessible::ProcessLoad()
 {
   mLoadState |= eCompletelyLoaded;
 
 #ifdef A11Y_LOG
--- a/accessible/ipc/DocAccessibleChildBase.cpp
+++ b/accessible/ipc/DocAccessibleChildBase.cpp
@@ -76,22 +76,35 @@ DocAccessibleChildBase::SerializeTree(Ac
 #endif
 
   for (uint32_t i = 0; i < childCount; i++) {
     SerializeTree(aRoot->GetChildAt(i), aTree);
   }
 }
 
 void
+DocAccessibleChildBase::InsertIntoIpcTree(Accessible* aParent,
+                                          Accessible* aChild,
+                                          uint32_t aIdxInParent)
+{
+  uint64_t parentID = aParent->IsDoc() ?
+    0 : reinterpret_cast<uint64_t>(aParent->UniqueID());
+  nsTArray<AccessibleData> shownTree;
+  ShowEventData data(parentID, aIdxInParent, shownTree, true);
+  SerializeTree(aChild, data.NewTree());
+  MaybeSendShowEvent(data, false);
+}
+
+void
 DocAccessibleChildBase::ShowEvent(AccShowEvent* aShowEvent)
 {
   Accessible* parent = aShowEvent->Parent();
   uint64_t parentID = parent->IsDoc() ? 0 : reinterpret_cast<uint64_t>(parent->UniqueID());
   uint32_t idxInParent = aShowEvent->GetAccessible()->IndexInParent();
   nsTArray<AccessibleData> shownTree;
-  ShowEventData data(parentID, idxInParent, shownTree);
+  ShowEventData data(parentID, idxInParent, shownTree, false);
   SerializeTree(aShowEvent->GetAccessible(), data.NewTree());
   MaybeSendShowEvent(data, aShowEvent->IsFromUserInput());
 }
 
 } // namespace a11y
 } // namespace mozilla
 
--- a/accessible/ipc/DocAccessibleChildBase.h
+++ b/accessible/ipc/DocAccessibleChildBase.h
@@ -40,16 +40,21 @@ public:
   }
 
   virtual void Shutdown()
   {
     DetachDocument();
     SendShutdown();
   }
 
+  /**
+   * Serializes a shown tree and sends it to the chrome process.
+   */
+  void InsertIntoIpcTree(Accessible* aParent,
+                         Accessible* aChild, uint32_t aIdxInParent);
   void ShowEvent(AccShowEvent* aShowEvent);
 
   virtual void ActorDestroy(ActorDestroyReason) override
   {
     if (!mDoc) {
       return;
     }
 
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -74,16 +74,21 @@ DocAccessibleParent::RecvShowEvent(const
   for (uint32_t i = 0; i < consumed; i++) {
     uint64_t id = aData.NewTree()[i].ID();
     MOZ_ASSERT(mAccessibles.GetEntry(id));
   }
 #endif
 
   MOZ_ASSERT(CheckDocTree());
 
+  // Just update, no events.
+  if (aData.EventSuppressed()) {
+    return IPC_OK();
+  }
+
   ProxyAccessible* target = parent->ChildAt(newChildIdx);
   ProxyShowHideEvent(target, parent, true, aFromUser);
 
   if (!nsCoreUtils::AccEventObserversExist()) {
     return IPC_OK();
   }
 
   uint32_t type = nsIAccessibleEvent::EVENT_SHOW;
--- a/accessible/ipc/other/PDocAccessible.ipdl
+++ b/accessible/ipc/other/PDocAccessible.ipdl
@@ -24,16 +24,17 @@ struct AccessibleData
   uint32_t Interfaces;
 };
 
 struct ShowEventData
 {
   uint64_t ID;
   uint32_t Idx;
   AccessibleData[] NewTree;
+  bool EventSuppressed;
 };
 
 struct Attribute
 {
   nsCString Name;
   nsString Value;
 };
 
--- a/accessible/ipc/win/DocAccessibleChild.h
+++ b/accessible/ipc/win/DocAccessibleChild.h
@@ -105,17 +105,18 @@ private:
 
   void PushDeferredEvent(UniquePtr<DeferredEvent> aEvent);
 
   struct SerializedShow final : public DeferredEvent
   {
     SerializedShow(DocAccessibleChild* aTarget,
                    ShowEventData& aEventData, bool aFromUser)
       : DeferredEvent(aTarget)
-      , mEventData(aEventData.ID(), aEventData.Idx(), nsTArray<AccessibleData>())
+      , mEventData(aEventData.ID(), aEventData.Idx(),
+                   nsTArray<AccessibleData>(), aEventData.EventSuppressed())
       , mFromUser(aFromUser)
     {
       // Since IPDL doesn't generate a move constructor for ShowEventData,
       // we move NewTree manually (ugh). We still construct with an empty
       // NewTree above so that the compiler catches any changes made to the
       // ShowEventData structure in IPDL.
       mEventData.NewTree() = Move(aEventData.NewTree());
     }
--- a/accessible/ipc/win/PDocAccessible.ipdl
+++ b/accessible/ipc/win/PDocAccessible.ipdl
@@ -24,16 +24,17 @@ struct AccessibleData
   uint32_t Interfaces;
 };
 
 struct ShowEventData
 {
   uint64_t ID;
   uint32_t Idx;
   AccessibleData[] NewTree;
+  bool EventSuppressed;
 };
 
 struct Attribute
 {
   nsCString Name;
   nsString Value;
 };
 
--- a/accessible/tests/mochitest/treeupdate/test_ariaowns.html
+++ b/accessible/tests/mochitest/treeupdate/test_ariaowns.html
@@ -519,19 +519,18 @@
 
       this.getID = function test8_getID() {
         return `Set ARIA owns on inaccessible span element that contains accessible children`;
       }
     }
 
     function test9_prepare() {
       this.eventSeq = [
-        new invokerChecker(EVENT_SHOW, () => {
-          let doc = getNode("t9_container").contentDocument;
-          return doc && doc.getElementById("container");
+        new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, () => {
+          return getNode("t9_container").contentDocument;
         })
       ];
 
       this.invoke = () => {
         // The \ before the final /script avoids the script from being terminated
         // by the html parser.
         getNode("t9_container").src = `data:text/html,
           <html><body></body>