mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1826857 - Move AnchorAt to Accessible and remove sync IPC. r=Jamie
Because the implementation only needs the accessible type and tree, we don't need to make an IPC call here. Differential Revision: https://phabricator.services.mozilla.com/D175288
This commit is contained in:
parent
4a2d824c2a
commit
489d1d11a0
@ -169,14 +169,12 @@ AtkObject* getObjectCB(AtkHyperlink* aLink, gint aLinkIndex) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (LocalAccessible* hyperlink = maiLink->GetAccHyperlink()) {
|
||||
LocalAccessible* anchor = hyperlink->AnchorAt(aLinkIndex);
|
||||
NS_ENSURE_TRUE(anchor, nullptr);
|
||||
|
||||
return AccessibleWrap::GetAtkObject(anchor);
|
||||
Accessible* acc = maiLink->Acc();
|
||||
if (!acc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RemoteAccessible* anchor = maiLink->Proxy()->AnchorAt(aLinkIndex);
|
||||
Accessible* anchor = acc->AnchorAt(aLinkIndex);
|
||||
return anchor ? GetWrapperFor(anchor) : nullptr;
|
||||
}
|
||||
|
||||
|
@ -382,6 +382,15 @@ uint32_t Accessible::AnchorCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Accessible* Accessible::AnchorAt(uint32_t aAnchorIndex) {
|
||||
if (IsImageMap()) {
|
||||
return ChildAt(aAnchorIndex);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(IsLink(), "GetAnchor is called on not hyper link!");
|
||||
return aAnchorIndex == 0 ? this : nullptr;
|
||||
}
|
||||
|
||||
#ifdef A11Y_LOG
|
||||
void Accessible::DebugDescription(nsCString& aDesc) const {
|
||||
aDesc.Truncate();
|
||||
|
@ -570,6 +570,11 @@ class Accessible {
|
||||
*/
|
||||
uint32_t AnchorCount();
|
||||
|
||||
/**
|
||||
* Returns an anchor accessible at the given index.
|
||||
*/
|
||||
Accessible* AnchorAt(uint32_t aAnchorIndex);
|
||||
|
||||
// Remote/Local types
|
||||
|
||||
virtual bool IsRemote() const = 0;
|
||||
|
@ -2776,11 +2776,6 @@ bool LocalAccessible::IsLink() const {
|
||||
return mParent && mParent->IsHyperText() && !IsText();
|
||||
}
|
||||
|
||||
LocalAccessible* LocalAccessible::AnchorAt(uint32_t aAnchorIndex) {
|
||||
MOZ_ASSERT(IsLink(), "GetAnchor is called on not hyper link!");
|
||||
return aAnchorIndex == 0 ? this : nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIURI> LocalAccessible::AnchorURIAt(
|
||||
uint32_t aAnchorIndex) const {
|
||||
MOZ_ASSERT(IsLink(), "AnchorURIAt is called on not hyper link!");
|
||||
|
@ -515,11 +515,6 @@ class LocalAccessible : public nsISupports, public Accessible {
|
||||
*/
|
||||
virtual bool IsLink() const override;
|
||||
|
||||
/**
|
||||
* Returns an anchor accessible at the given index.
|
||||
*/
|
||||
virtual LocalAccessible* AnchorAt(uint32_t aAnchorIndex);
|
||||
|
||||
/**
|
||||
* Returns an anchor URI at the given index.
|
||||
*/
|
||||
|
@ -40,10 +40,6 @@ role HTMLImageMapAccessible::NativeRole() const { return roles::IMAGE_MAP; }
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// HTMLImageMapAccessible: HyperLinkAccessible
|
||||
|
||||
LocalAccessible* HTMLImageMapAccessible::AnchorAt(uint32_t aAnchorIndex) {
|
||||
return LocalChildAt(aAnchorIndex);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIURI> HTMLImageMapAccessible::AnchorURIAt(
|
||||
uint32_t aAnchorIndex) const {
|
||||
LocalAccessible* area = LocalChildAt(aAnchorIndex);
|
||||
|
@ -26,7 +26,6 @@ class HTMLImageMapAccessible final : public ImageAccessible {
|
||||
virtual a11y::role NativeRole() const override;
|
||||
|
||||
// HyperLinkAccessible
|
||||
virtual LocalAccessible* AnchorAt(uint32_t aAnchorIndex) override;
|
||||
virtual already_AddRefed<nsIURI> AnchorURIAt(
|
||||
uint32_t aAnchorIndex) const override;
|
||||
|
||||
|
@ -111,8 +111,6 @@ LayoutDeviceIntSize ImageSize();
|
||||
|
||||
void AnchorURIAt(uint32_t aIndex, nsCString& aURI, bool* aOk);
|
||||
|
||||
RemoteAccessible* AnchorAt(uint32_t aIndex);
|
||||
|
||||
uint32_t LinkCount();
|
||||
|
||||
RemoteAccessible* TableOfACell();
|
||||
|
@ -628,24 +628,6 @@ mozilla::ipc::IPCResult DocAccessibleChild::RecvAnchorURIAt(
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult DocAccessibleChild::RecvAnchorAt(const uint64_t& aID,
|
||||
const uint32_t& aIndex,
|
||||
uint64_t* aIDOfAnchor,
|
||||
bool* aOk) {
|
||||
*aIDOfAnchor = 0;
|
||||
*aOk = false;
|
||||
LocalAccessible* acc = IdToAccessibleLink(aID);
|
||||
if (acc) {
|
||||
LocalAccessible* anchor = acc->AnchorAt(aIndex);
|
||||
if (anchor) {
|
||||
*aIDOfAnchor = reinterpret_cast<uint64_t>(anchor->UniqueID());
|
||||
*aOk = true;
|
||||
}
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult DocAccessibleChild::RecvLinkCount(const uint64_t& aID,
|
||||
uint32_t* aCount) {
|
||||
HyperTextAccessible* acc = IdToHyperTextAccessible(aID);
|
||||
|
@ -224,10 +224,6 @@ class DocAccessibleChild : public DocAccessibleChildBase {
|
||||
const uint32_t& aIndex,
|
||||
nsCString* aURI,
|
||||
bool* aOk) override;
|
||||
virtual mozilla::ipc::IPCResult RecvAnchorAt(const uint64_t& aID,
|
||||
const uint32_t& aIndex,
|
||||
uint64_t* aIDOfAnchor,
|
||||
bool* aOk) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvLinkCount(const uint64_t& aID,
|
||||
uint32_t* aCount) override;
|
||||
|
@ -241,7 +241,6 @@ child:
|
||||
[Nested=inside_sync] sync StartOffset(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
|
||||
[Nested=inside_sync] sync EndOffset(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
|
||||
[Nested=inside_sync] sync AnchorURIAt(uint64_t aID, uint32_t aIndex) returns(nsCString aURI, bool aOk);
|
||||
[Nested=inside_sync] sync AnchorAt(uint64_t aID, uint32_t aIndex) returns(uint64_t aIDOfAnchor, bool aOk);
|
||||
|
||||
[Nested=inside_sync] sync LinkCount(uint64_t aID) returns(uint32_t aCount);
|
||||
[Nested=inside_sync] sync LinkIndexAtOffset(uint64_t aID, uint32_t aOffset) returns(int32_t aIndex);
|
||||
|
@ -433,13 +433,6 @@ void RemoteAccessible::AnchorURIAt(uint32_t aIndex, nsCString& aURI,
|
||||
Unused << mDoc->SendAnchorURIAt(mID, aIndex, &aURI, aOk);
|
||||
}
|
||||
|
||||
RemoteAccessible* RemoteAccessible::AnchorAt(uint32_t aIndex) {
|
||||
uint64_t id = 0;
|
||||
bool ok = false;
|
||||
Unused << mDoc->SendAnchorAt(mID, aIndex, &id, &ok);
|
||||
return ok ? mDoc->GetAccessible(id) : nullptr;
|
||||
}
|
||||
|
||||
uint32_t RemoteAccessible::LinkCount() {
|
||||
uint32_t retVal = 0;
|
||||
Unused << mDoc->SendLinkCount(mID, &retVal);
|
||||
|
@ -781,28 +781,6 @@ void RemoteAccessible::ScrollSubstringToPoint(int32_t aStartOffset,
|
||||
static_cast<long>(aX), static_cast<long>(aY));
|
||||
}
|
||||
|
||||
RemoteAccessible* RemoteAccessible::AnchorAt(uint32_t aIdx) {
|
||||
if (StaticPrefs::accessibility_cache_enabled_AtStartup()) {
|
||||
// Not yet supported by the cache.
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<IAccessibleHyperlink> link =
|
||||
QueryInterface<IAccessibleHyperlink>(this);
|
||||
if (!link) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VARIANT anchor;
|
||||
if (FAILED(link->get_anchor(aIdx, &anchor))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(anchor.vt == VT_UNKNOWN);
|
||||
RemoteAccessible* proxyAnchor = GetProxyFor(Document(), anchor.punkVal);
|
||||
anchor.punkVal->Release();
|
||||
return proxyAnchor;
|
||||
}
|
||||
|
||||
void RemoteAccessible::DOMNodeID(nsString& aID) const {
|
||||
if (StaticPrefs::accessibility_cache_enabled_AtStartup()) {
|
||||
return RemoteAccessibleBase<RemoteAccessible>::DOMNodeID(aID);
|
||||
|
@ -24,6 +24,7 @@ prefs =
|
||||
[browser_caching_description.js]
|
||||
[browser_caching_document_props.js]
|
||||
[browser_caching_domnodeid.js]
|
||||
[browser_caching_hyperlink.js]
|
||||
[browser_caching_innerHTML.js]
|
||||
skip-if = os != 'win'
|
||||
[browser_caching_interfaces.js]
|
||||
|
182
accessible/tests/browser/e10s/browser_caching_hyperlink.js
Normal file
182
accessible/tests/browser/e10s/browser_caching_hyperlink.js
Normal file
@ -0,0 +1,182 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
function testLinkIndexAtOffset(id, offset, index) {
|
||||
let htAcc = getAccessible(id, [nsIAccessibleHyperText]);
|
||||
is(
|
||||
htAcc.getLinkIndexAtOffset(offset),
|
||||
index,
|
||||
"Wrong link index at offset " + offset + " for ID " + id + "!"
|
||||
);
|
||||
}
|
||||
|
||||
function testThis(
|
||||
paragraph,
|
||||
id,
|
||||
charIndex,
|
||||
expectedLinkIndex,
|
||||
expectedAnchors,
|
||||
valid = true
|
||||
) {
|
||||
testLinkIndexAtOffset(paragraph, charIndex, expectedLinkIndex);
|
||||
|
||||
let linkAcc = paragraph.getLinkAt(expectedLinkIndex);
|
||||
ok(linkAcc, "No accessible for link " + id + "!");
|
||||
|
||||
is(linkAcc.valid, valid, `${id} is valid.`);
|
||||
|
||||
let linkIndex = paragraph.getLinkIndex(linkAcc);
|
||||
is(linkIndex, expectedLinkIndex, "Wrong link index for " + id + "!");
|
||||
|
||||
is(linkAcc.anchorCount, expectedAnchors.length, "Correct number of anchors");
|
||||
for (let i = 0; i < expectedAnchors.length; i++) {
|
||||
is(
|
||||
getAccessibleDOMNodeID(linkAcc.getAnchor(i)),
|
||||
expectedAnchors[i],
|
||||
`Wrong anchor at ${i} for "${id}"`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test hyperlinks
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<p id="testParagraph"><br
|
||||
>Simple link:<br
|
||||
><a id="NormalHyperlink" href="http://www.mozilla.org">Mozilla Foundation</a><br
|
||||
>ARIA link:<br
|
||||
><span id="AriaHyperlink" role="link"
|
||||
onclick="window.open('http://www.mozilla.org/');"
|
||||
tabindex="0">Mozilla Foundation Home</span><br
|
||||
>Invalid, non-focusable hyperlink:<br
|
||||
><span id="InvalidAriaHyperlink" role="link" aria-invalid="true"
|
||||
onclick="window.open('http:/www.mozilla.org/');">Invalid link</span><br
|
||||
>Image map:<br
|
||||
><map name="atoz_map"><area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#b"
|
||||
coords="17,0,30,14"
|
||||
id="b"
|
||||
shape="rect"></area
|
||||
><area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#a"
|
||||
coords="0,0,13,14"
|
||||
id="a"
|
||||
shape="rect"></area></map
|
||||
><img width="447" id="imgmap"
|
||||
height="15"
|
||||
usemap="#atoz_map"
|
||||
src="../letters.gif"></img><br
|
||||
>Empty link:<br
|
||||
><a id="emptyLink" href=""><img src=""></img></a><br
|
||||
>Link with embedded span<br
|
||||
><a id="LinkWithSpan" href="http://www.heise.de/"><span lang="de">Heise Online</span></a><br
|
||||
>Named anchor, must not have "linked" state for it to be exposed correctly:<br
|
||||
><a id="namedAnchor" name="named_anchor">This should never be of state_linked</a>
|
||||
</p>
|
||||
`,
|
||||
function(browser, accDoc) {
|
||||
const paragraph = findAccessibleChildByID(accDoc, "testParagraph", [
|
||||
nsIAccessibleHyperText,
|
||||
]);
|
||||
is(paragraph.linkCount, 7, "Wrong link count for paragraph!");
|
||||
|
||||
// normal hyperlink
|
||||
testThis(paragraph, "NormalHyperlink", 14, 0, ["NormalHyperlink"]);
|
||||
|
||||
// ARIA hyperlink
|
||||
testThis(paragraph, "AriaHyperlink", 27, 1, ["AriaHyperlink"]);
|
||||
|
||||
// ARIA hyperlink with status invalid
|
||||
testThis(
|
||||
paragraph,
|
||||
"InvalidAriaHyperlink",
|
||||
63,
|
||||
2,
|
||||
["InvalidAriaHyperlink"],
|
||||
false
|
||||
);
|
||||
|
||||
// image map, but not its link children. They are not part of hypertext.
|
||||
testThis(paragraph, "imgmap", 76, 3, ["b", "a"]);
|
||||
|
||||
// empty hyperlink
|
||||
testThis(paragraph, "emptyLink", 90, 4, ["emptyLink"]);
|
||||
|
||||
// normal hyperlink with embedded span
|
||||
testThis(paragraph, "LinkWithSpan", 116, 5, ["LinkWithSpan"]);
|
||||
|
||||
// Named anchor
|
||||
testThis(paragraph, "namedAnchor", 193, 6, ["namedAnchor"]);
|
||||
},
|
||||
{
|
||||
chrome: true,
|
||||
topLevel: !isWinNoCache,
|
||||
iframe: !isWinNoCache,
|
||||
remoteIframe: !isWinNoCache,
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Test paragraph with link
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<p id="p"><a href="http://mozilla.org">mozilla.org</a></p>
|
||||
`,
|
||||
function(browser, accDoc) {
|
||||
// Paragraph with link
|
||||
const p = findAccessibleChildByID(accDoc, "p", [nsIAccessibleHyperText]);
|
||||
const link = p.getLinkAt(0);
|
||||
is(link, p.getChildAt(0), "Wrong link for p2");
|
||||
is(p.linkCount, 1, "Wrong link count for p2");
|
||||
},
|
||||
{
|
||||
chrome: true,
|
||||
topLevel: !isWinNoCache,
|
||||
iframe: !isWinNoCache,
|
||||
remoteIframe: !isWinNoCache,
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Test paragraph with link
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<p id="p"><a href="www">mozilla</a><a href="www">mozilla</a><span> te</span><span>xt </span><a href="www">mozilla</a></p>
|
||||
`,
|
||||
function(browser, accDoc) {
|
||||
// Paragraph with link
|
||||
const p = findAccessibleChildByID(accDoc, "p", [nsIAccessibleHyperText]);
|
||||
|
||||
// getLinkIndexAtOffset, causes the offsets to be cached;
|
||||
testLinkIndexAtOffset(p, 0, 0); // 1st 'mozilla' link
|
||||
testLinkIndexAtOffset(p, 1, 1); // 2nd 'mozilla' link
|
||||
testLinkIndexAtOffset(p, 2, -1); // ' ' of ' te' text node
|
||||
testLinkIndexAtOffset(p, 3, -1); // 't' of ' te' text node
|
||||
testLinkIndexAtOffset(p, 5, -1); // 'x' of 'xt ' text node
|
||||
testLinkIndexAtOffset(p, 7, -1); // ' ' of 'xt ' text node
|
||||
testLinkIndexAtOffset(p, 8, 2); // 3d 'mozilla' link
|
||||
testLinkIndexAtOffset(p, 9, 2); // the end, latest link
|
||||
|
||||
// the second pass to make sure link indexes are calculated propertly from
|
||||
// cached offsets.
|
||||
testLinkIndexAtOffset(p, 0, 0); // 1st 'mozilla' link
|
||||
testLinkIndexAtOffset(p, 1, 1); // 2nd 'mozilla' link
|
||||
testLinkIndexAtOffset(p, 2, -1); // ' ' of ' te' text node
|
||||
testLinkIndexAtOffset(p, 3, -1); // 't' of ' te' text node
|
||||
testLinkIndexAtOffset(p, 5, -1); // 'x' of 'xt ' text node
|
||||
testLinkIndexAtOffset(p, 7, -1); // ' ' of 'xt ' text node
|
||||
testLinkIndexAtOffset(p, 8, 2); // 3d 'mozilla' link
|
||||
testLinkIndexAtOffset(p, 9, 2); // the end, latest link
|
||||
},
|
||||
{
|
||||
chrome: true,
|
||||
topLevel: !isWinNoCache,
|
||||
iframe: !isWinNoCache,
|
||||
remoteIframe: !isWinNoCache,
|
||||
}
|
||||
);
|
@ -52,7 +52,7 @@ ia2AccessibleHyperlink::get_anchor(long aIndex, VARIANT* aAnchor) {
|
||||
|
||||
VariantInit(aAnchor);
|
||||
|
||||
LocalAccessible* thisObj = LocalAcc();
|
||||
Accessible* thisObj = Acc();
|
||||
if (!thisObj) {
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
}
|
||||
@ -62,12 +62,10 @@ ia2AccessibleHyperlink::get_anchor(long aIndex, VARIANT* aAnchor) {
|
||||
|
||||
if (!thisObj->IsLink()) return S_FALSE;
|
||||
|
||||
AccessibleWrap* anchor =
|
||||
static_cast<AccessibleWrap*>(thisObj->AnchorAt(aIndex));
|
||||
Accessible* anchor = thisObj->AnchorAt(aIndex);
|
||||
if (!anchor) return S_FALSE;
|
||||
|
||||
RefPtr<IAccessible> result;
|
||||
anchor->GetNativeInterface(getter_AddRefs(result));
|
||||
RefPtr<IAccessible> result = MsaaAccessible::GetFrom(anchor);
|
||||
result.forget(&aAnchor->punkVal);
|
||||
aAnchor->vt = VT_UNKNOWN;
|
||||
return S_OK;
|
||||
|
@ -104,20 +104,12 @@ xpcAccessibleHyperLink::GetAnchor(int32_t aIndex, nsIAccessible** aAccessible) {
|
||||
|
||||
if (aIndex < 0) return NS_ERROR_INVALID_ARG;
|
||||
|
||||
if (Intl()->IsLocal()) {
|
||||
if (aIndex >= static_cast<int32_t>(Intl()->AsLocal()->AnchorCount())) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*aAccessible = ToXPC(Intl()->AsLocal()->AnchorAt(aIndex)));
|
||||
} else {
|
||||
#if defined(XP_WIN)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#else
|
||||
NS_IF_ADDREF(*aAccessible = ToXPC(Intl()->AsRemote()->AnchorAt(aIndex)));
|
||||
#endif
|
||||
if (aIndex >= static_cast<int32_t>(Intl()->AnchorCount())) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*aAccessible = ToXPC(Intl()->AnchorAt(aIndex)));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user