Bug 1768726 - Make RemoteAccessibleBase::BoundsWithOffset thread safe for Android. r=morgan

In Android we need to keep the remote accessible methods thread safe. That means no direct references to local accessibles, or anything DOM or layout.

We have the advantage of always being remote except for a 0 offset browser element, and no support for full page zoom.

Also removed the visual/layout viewport offset in the bounds method since
the top level doc will always have its visual and layout viewport match.

Differential Revision: https://phabricator.services.mozilla.com/D146006
This commit is contained in:
Eitan Isaacson 2022-05-10 22:57:32 +00:00
Родитель 780d656a9c
Коммит 7e7246091a
1 изменённых файлов: 32 добавлений и 32 удалений

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

@ -396,6 +396,7 @@ LayoutDeviceIntRect RemoteAccessibleBase<Derived>::BoundsWithOffset(
Maybe<nsRect> maybeBounds = RetrieveCachedBounds();
if (maybeBounds) {
nsRect bounds = *maybeBounds;
#if !defined(ANDROID)
dom::CanonicalBrowsingContext* cbc =
static_cast<dom::BrowserParent*>(mDoc->Manager())
->GetBrowsingContext()
@ -403,6 +404,11 @@ LayoutDeviceIntRect RemoteAccessibleBase<Derived>::BoundsWithOffset(
dom::BrowserParent* bp = cbc->GetBrowserParent();
nsPresContext* presContext =
bp->GetOwnerElement()->OwnerDoc()->GetPresContext();
float fullZoom = cbc->GetFullZoom();
#else
// In Android the FullZoom is always 1.0 since we use APZ/resolution zoom.
float fullZoom = 1.0;
#endif
if (aOffset.isSome()) {
// The rect we've passed in is in app units, so no conversion needed.
@ -411,7 +417,7 @@ LayoutDeviceIntRect RemoteAccessibleBase<Derived>::BoundsWithOffset(
// text bounds, which already have their zoom level
// applied. Remove it, because we'll multiply it back
// in later on.
internalRect.ScaleRoundOut(1 / cbc->GetFullZoom());
internalRect.ScaleRoundOut(1 / fullZoom);
bounds.SetRectX(bounds.x + internalRect.x, internalRect.width);
bounds.SetRectY(bounds.y + internalRect.y, internalRect.height);
}
@ -421,29 +427,7 @@ LayoutDeviceIntRect RemoteAccessibleBase<Derived>::BoundsWithOffset(
LayoutDeviceIntRect devPxBounds;
const Accessible* acc = Parent();
while (acc) {
if (LocalAccessible* localAcc =
const_cast<Accessible*>(acc)->AsLocal()) {
// LocalAccessible::Bounds returns screen-relative bounds in
// dev pixels.
LayoutDeviceIntRect localBounds = localAcc->Bounds();
// Convert our existing `bounds` rect from app units to dev pixels
devPxBounds = LayoutDeviceIntRect::FromAppUnitsToNearest(
bounds, presContext->AppUnitsPerDevPixel());
// We factor in our zoom level before offsetting by
// `localBounds`, which has already taken zoom into account.
devPxBounds.ScaleRoundOut(cbc->GetFullZoom());
// The root document will always have an APZ resolution of 1,
// so we don't factor in its scale here. We also don't scale
// by GetFullZoom because LocalAccessible::Bounds already does
// that.
devPxBounds.MoveBy(localBounds.X(), localBounds.Y());
break;
}
while (acc && acc->IsRemote()) {
RemoteAccessible* remoteAcc = const_cast<Accessible*>(acc)->AsRemote();
if (Maybe<nsRect> maybeRemoteBounds =
@ -484,15 +468,31 @@ LayoutDeviceIntRect RemoteAccessibleBase<Derived>::BoundsWithOffset(
acc = acc->Parent();
}
PresShell* presShell = presContext->PresShell();
#if !defined(ANDROID)
// This block is not thread safe because it queries a LocalAccessible,
// the BrowsingContext, PresContext, etc. It is also not needed in
// Android since the only local accessible is the outer doc browser that
// has an offset of 0 and a FullZoom value of 1.0.
if (LocalAccessible* localAcc = const_cast<Accessible*>(acc)->AsLocal()) {
// LocalAccessible::Bounds returns screen-relative bounds in
// dev pixels.
LayoutDeviceIntRect localBounds = localAcc->Bounds();
// Our relative bounds are pulled from the coordinate space of the layout
// viewport, but we need them to be in the coordinate space of the visual
// viewport. We calculate the difference and translate our bounds here.
nsPoint viewportOffset = presShell->GetVisualViewportOffset() -
presShell->GetLayoutViewportOffset();
devPxBounds.MoveBy(-(LayoutDeviceIntPoint::FromAppUnitsToNearest(
viewportOffset, presContext->AppUnitsPerDevPixel())));
// Convert our existing `bounds` rect from app units to dev pixels
devPxBounds = LayoutDeviceIntRect::FromAppUnitsToNearest(
bounds, presContext->AppUnitsPerDevPixel());
// We factor in our zoom level before offsetting by
// `localBounds`, which has already taken zoom into account.
devPxBounds.ScaleRoundOut(fullZoom);
// The root document will always have an APZ resolution of 1,
// so we don't factor in its scale here. We also don't scale
// by GetFullZoom because LocalAccessible::Bounds already does
// that.
devPxBounds.MoveBy(localBounds.X(), localBounds.Y());
}
#endif
return devPxBounds;
}