bug 1074917 - teach atk to get states from proxies r=surkov, davidb, mrbkap
☠☠ backed out by 3af437d9bb50 ☠ ☠
authorTrevor Saunders <trev.saunders@gmail.com>
Tue, 23 Sep 2014 04:35:33 -0400
changeset 210424 e802d78f9459ac85f596bf10597a9cc42955d86c
parent 210423 72b3317ead188c5cd995cbfe332cc5894cd96a18
child 210425 d5c1c2837d530539ee8edc2835c61f48009fca0b
push id50448
push usertrev.saunders@gmail.com
push dateWed, 15 Oct 2014 06:23:35 +0000
treeherdermozilla-inbound@e802d78f9459 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssurkov, davidb, mrbkap
bugs1074917
milestone36.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 1074917 - teach atk to get states from proxies r=surkov, davidb, mrbkap We need to implement things like https://developer.gnome.org/atk/unstable/AtkObject.html#atk-object-ref-state-set and the same basic thing on windows. That API is fundamentally sync, but the information necessary to implement it is only available in the child process. That seems to leave us with two options, either we can use sync ipc or we can use async ipc but spin a nested event loop. If we were to spin nested event loops we'd have to be careful to make sure a11y didn't do anything until the nested event loop was done, and then a11y would have to deal with whatever changed. I'm not sure that will work, and since the system is probably waiting for the accessibility information anyway I don't think we get much out of spinning the event loop. So I think its somewhat less bad to use sync ipc here.
accessible/atk/AccessibleWrap.cpp
accessible/ipc/DocAccessibleChild.cpp
accessible/ipc/DocAccessibleChild.h
accessible/ipc/PDocAccessible.ipdl
accessible/ipc/ProxyAccessible.cpp
accessible/ipc/ProxyAccessible.h
--- a/accessible/atk/AccessibleWrap.cpp
+++ b/accessible/atk/AccessibleWrap.cpp
@@ -887,29 +887,28 @@ TranslateStates(uint64_t aState, AtkStat
     bitMask <<= 1;
     ++ stateIndex;
   }
 }
 
 AtkStateSet *
 refStateSetCB(AtkObject *aAtkObj)
 {
-    AtkStateSet *state_set = nullptr;
-    state_set = ATK_OBJECT_CLASS(parent_class)->ref_state_set(aAtkObj);
+  AtkStateSet *state_set = nullptr;
+  state_set = ATK_OBJECT_CLASS(parent_class)->ref_state_set(aAtkObj);
 
-    AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
-    if (!accWrap) {
-        TranslateStates(states::DEFUNCT, state_set);
-        return state_set;
-    }
+  AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
+  if (accWrap)
+    TranslateStates(accWrap->State(), state_set);
+  else if (ProxyAccessible* proxy = GetProxy(aAtkObj))
+    TranslateStates(proxy->State(), state_set);
+  else
+    TranslateStates(states::DEFUNCT, state_set);
 
-    // Map states
-    TranslateStates(accWrap->State(), state_set);
-
-    return state_set;
+  return state_set;
 }
 
 static void
 UpdateAtkRelation(RelationType aType, Accessible* aAcc,
                   AtkRelationType aAtkType, AtkRelationSet* aAtkSet)
 {
   if (aAtkType == ATK_RELATION_NULL)
     return;
--- a/accessible/ipc/DocAccessibleChild.cpp
+++ b/accessible/ipc/DocAccessibleChild.cpp
@@ -31,10 +31,24 @@ DocAccessibleChild::ShowEvent(AccShowEve
   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);
   SerializeTree(aShowEvent->GetAccessible(), data.NewTree());
   SendShowEvent(data);
 }
+
+bool
+DocAccessibleChild::RecvState(const uint64_t& aID, uint64_t* aState)
+{
+  Accessible* acc = mDoc->GetAccessibleByUniqueID((void*)aID);
+  if (!acc) {
+    *aState = states::DEFUNCT;
+    return true;
+  }
+
+  *aState = acc->State();
+
+  return true;
 }
 }
+}
--- a/accessible/ipc/DocAccessibleChild.h
+++ b/accessible/ipc/DocAccessibleChild.h
@@ -28,16 +28,21 @@ public:
   ~DocAccessibleChild()
   {
     mDoc->SetIPCDoc(nullptr);
     MOZ_COUNT_DTOR(DocAccessibleChild);
   }
 
   void ShowEvent(AccShowEvent* aShowEvent);
 
+  /*
+   * Return the state for the accessible with given ID.
+   */
+  virtual bool RecvState(const uint64_t& aID, uint64_t* aState) MOZ_OVERRIDE;
+
 private:
   DocAccessible* mDoc;
 };
 
 }
 }
 
 #endif
--- a/accessible/ipc/PDocAccessible.ipdl
+++ b/accessible/ipc/PDocAccessible.ipdl
@@ -19,26 +19,29 @@ struct AccessibleData
 
 struct ShowEventData
 {
   uint64_t ID;
   uint32_t Idx;
   AccessibleData[] NewTree;
 };
 
-protocol PDocAccessible
+prio(normal upto high) sync protocol PDocAccessible
 {
   manager PContent;
 
 parent:
   __delete__();
 
   /*
    * Notify the parent process the document in the child process is firing an
    * event.
    */
   Event(uint32_t type);
   ShowEvent(ShowEventData data);
   HideEvent(uint64_t aRootID);
+
+child:
+  prio(high) sync State(uint64_t aID) returns(uint64_t states);
 };
 
 }
 }
--- a/accessible/ipc/ProxyAccessible.cpp
+++ b/accessible/ipc/ProxyAccessible.cpp
@@ -1,16 +1,17 @@
 /* -*- 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 "ProxyAccessible.h"
 #include "DocAccessibleParent.h"
+#include "mozilla/unused.h"
 #include "mozilla/a11y/Platform.h"
 
 namespace mozilla {
 namespace a11y {
 
 void
 ProxyAccessible::Shutdown()
 {
@@ -33,10 +34,18 @@ ProxyAccessible::SetChildDoc(DocAccessib
     mChildren.AppendElement(aParent);
     mOuterDoc = true;
   } else {
     MOZ_ASSERT(mChildren.Length() == 1);
     mChildren.Clear();
     mOuterDoc = false;
   }
 }
+
+uint64_t
+ProxyAccessible::State() const
+{
+  uint64_t state = 0;
+  unused << mDoc->SendState(mID, &state);
+  return state;
 }
 }
+}
--- a/accessible/ipc/ProxyAccessible.h
+++ b/accessible/ipc/ProxyAccessible.h
@@ -49,16 +49,21 @@ public:
    */
   ProxyAccessible* Parent() const { return mParent; }
 
   /**
    * Get the role of the accessible we're proxying.
    */
   role Role() const { return mRole; }
 
+  /*
+   * Return the states for the proxied accessible.
+   */
+  uint64_t State() 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.