Bug 1479039 - Implement java portion of focus path cache. r=snorp,yzen

Differential Revision: https://phabricator.services.mozilla.com/D11215

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Eitan Isaacson 2018-11-12 16:41:40 +00:00
Родитель 970933ad81
Коммит 956b93179f
5 изменённых файлов: 86 добавлений и 15 удалений

Просмотреть файл

@ -226,7 +226,13 @@ DocAccessibleWrap::CacheFocusPath(AccessibleWrap* aAccessible)
}
ipcDoc->SendBatch(eBatch_FocusPath, cacheData);
} else {
// XXX: Local codepath, next patch
} else if (SessionAccessibility* sessionAcc = SessionAccessibility::GetInstanceFor(this)) {
nsTArray<AccessibleWrap*> accessibles;
for (AccessibleWrap* acc = aAccessible; acc && acc != this->Parent();
acc = static_cast<AccessibleWrap*>(acc->Parent())) {
accessibles.AppendElement(acc);
}
sessionAcc->ReplaceFocusPathCache(accessibles);
}
}

Просмотреть файл

@ -222,7 +222,7 @@ a11y::ProxyBatch(ProxyAccessible* aDocument,
sessionAcc->ReplaceViewportCache(accWraps, aData);
break;
case DocAccessibleWrap::eBatch_FocusPath:
// XXX: Next patch
sessionAcc->ReplaceFocusPathCache(accWraps, aData);
break;
default:
MOZ_ASSERT_UNREACHABLE("Unknown batch type.");

Просмотреть файл

@ -13,6 +13,7 @@
#include "RootAccessibleWrap.h"
#include "nsAccessibilityService.h"
#include "nsViewManager.h"
#include "nsIPersistentProperties2.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/a11y/DocAccessibleParent.h"
@ -340,7 +341,8 @@ SessionAccessibility::ReplaceViewportCache(const nsTArray<AccessibleWrap*>& aAcc
AccessibleWrap* acc = aAccessibles.ElementAt(i);
if (aData.Length() == aAccessibles.Length()) {
const BatchData& data = aData.ElementAt(i);
infos->SetElement(i, acc->ToSmallBundle(data.State(), data.Bounds()));
auto bundle = acc->ToSmallBundle(data.State(), data.Bounds());
infos->SetElement(i, bundle);
} else {
infos->SetElement(i, acc->ToSmallBundle());
}
@ -348,3 +350,33 @@ SessionAccessibility::ReplaceViewportCache(const nsTArray<AccessibleWrap*>& aAcc
mSessionAccessibility->ReplaceViewportCache(infos);
}
void
SessionAccessibility::ReplaceFocusPathCache(const nsTArray<AccessibleWrap*>& aAccessibles,
const nsTArray<BatchData>& aData)
{
auto infos = jni::ObjectArray::New<java::GeckoBundle>(aAccessibles.Length());
for (size_t i = 0; i < aAccessibles.Length(); i++) {
AccessibleWrap* acc = aAccessibles.ElementAt(i);
if (aData.Length() == aAccessibles.Length()) {
const BatchData& data = aData.ElementAt(i);
nsCOMPtr<nsIPersistentProperties> props =
AccessibleWrap::AttributeArrayToProperties(data.Attributes());
auto bundle = acc->ToBundle(data.State(),
data.Bounds(),
data.Name(),
data.TextValue(),
data.DOMNodeID(),
data.CurValue(),
data.MinValue(),
data.MaxValue(),
data.Step(),
props);
infos->SetElement(i, bundle);
} else {
infos->SetElement(i, acc->ToBundle());
}
}
mSessionAccessibility->ReplaceFocusPathCache(infos);
}

Просмотреть файл

@ -109,6 +109,9 @@ public:
void ReplaceViewportCache(const nsTArray<AccessibleWrap*>& aAccessibles,
const nsTArray<BatchData>& aData = nsTArray<BatchData>());
void ReplaceFocusPathCache(const nsTArray<AccessibleWrap*>& aAccessibles,
const nsTArray<BatchData>& aData = nsTArray<BatchData>());
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SessionAccessibility)
private:

Просмотреть файл

@ -34,6 +34,8 @@ import android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo;
import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import java.util.LinkedList;
public class SessionAccessibility {
private static final String LOGTAG = "GeckoAccessibility";
@ -250,20 +252,28 @@ public class SessionAccessibility {
}
private boolean isNodeCached(final int virtualViewId) {
return mViewportCache.get(virtualViewId) != null;
return mViewportCache.get(virtualViewId) != null || mFocusPathCache.get(virtualViewId) != null;
}
private AccessibilityNodeInfo getNodeFromCache(final int virtualViewId) {
GeckoBundle bundle = mViewportCache.get(virtualViewId);
if (bundle == null) {
Log.e(LOGTAG, "No node for " + virtualViewId + " cache size: " + mViewportCache.size());
return null;
private synchronized AccessibilityNodeInfo getNodeFromCache(final int virtualViewId) {
AccessibilityNodeInfo node = null;
for (SparseArray<GeckoBundle> cache : mCaches) {
GeckoBundle bundle = cache.get(virtualViewId);
if (bundle == null) {
continue;
}
if (node == null) {
node = AccessibilityNodeInfo.obtain(mView, virtualViewId);
}
populateNodeFromBundle(node, bundle, true);
}
AccessibilityNodeInfo node = AccessibilityNodeInfo.obtain(mView, virtualViewId);
populateNodeFromBundle(node, bundle, true);
return node;
if (node == null) {
Log.e(LOGTAG, "No cached node for " + virtualViewId);
}
return node;
}
private void populateNodeFromBundle(final AccessibilityNodeInfo node, final GeckoBundle nodeInfo, final boolean fromCache) {
@ -288,7 +298,10 @@ public class SessionAccessibility {
// The basics
node.setPackageName(GeckoAppShell.getApplicationContext().getPackageName());
node.setClassName(getClassName(nodeInfo.getInt("className")));
node.setText(nodeInfo.getString("text", ""));
if (nodeInfo.containsKey("text")) {
node.setText(nodeInfo.getString("text"));
}
// Add actions
node.addAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT);
@ -451,6 +464,10 @@ public class SessionAccessibility {
private int mAccessibilityFocusedNode = 0;
// Viewport cache
final SparseArray<GeckoBundle> mViewportCache = new SparseArray<>();
// Focus cache
final SparseArray<GeckoBundle> mFocusPathCache = new SparseArray<>();
// List of caches in descending order from last updated.
LinkedList<SparseArray<GeckoBundle>> mCaches = new LinkedList<>();
/* package */ SessionAccessibility(final GeckoSession session) {
mSession = session;
@ -680,12 +697,25 @@ public class SessionAccessibility {
}
@WrapForJNI(calledFrom = "gecko")
private void replaceViewportCache(final GeckoBundle[] bundles) {
private synchronized void replaceViewportCache(final GeckoBundle[] bundles) {
mViewportCache.clear();
for (GeckoBundle bundle : bundles) {
if (bundle == null) { continue; }
mViewportCache.append(bundle.getInt("id"), bundle);
}
mCaches.remove(mViewportCache);
mCaches.add(mViewportCache);
}
@WrapForJNI(calledFrom = "gecko")
private synchronized void replaceFocusPathCache(final GeckoBundle[] bundles) {
mFocusPathCache.clear();
for (GeckoBundle bundle : bundles) {
if (bundle == null) { continue; }
mFocusPathCache.append(bundle.getInt("id"), bundle);
}
mCaches.remove(mFocusPathCache);
mCaches.add(mFocusPathCache);
}
}
}