/* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*- * 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/. */
void SessionAccessibility::Paste(int32_t aID) { if (Accessible* acc = GetAccessibleByID(aID)) { if (auto* textAcc = acc->AsHyperTextBase()) {
textAcc->PasteText(nsIAccessibleText::TEXT_OFFSET_CARET);
}
}
}
RefPtr<SessionAccessibility> SessionAccessibility::GetInstanceFor(
Accessible* aAccessible) {
MOZ_ASSERT(NS_IsMainThread()); if (LocalAccessible* localAcc = aAccessible->AsLocal()) {
DocAccessible* docAcc = localAcc->Document(); // If the accessible is being shutdown from the doc's shutdown // the doc accessible won't have a ref to a presshell anymore, // but we should have a ref to the DOM document node, and the DOM doc // has a ref to the presshell.
dom::Document* doc = docAcc ? docAcc->DocumentNode() : nullptr; if (doc && doc->IsContentDocument()) { // Only content accessibles should have an associated SessionAccessible. return GetInstanceFor(doc->GetPresShell());
}
} else {
dom::CanonicalBrowsingContext* cbc = static_cast<dom::BrowserParent*>(
aAccessible->AsRemote()->Document()->Manager())
->GetBrowsingContext()
->Top();
dom::BrowserParent* bp = cbc->GetBrowserParent(); if (!bp) {
bp = static_cast<dom::BrowserParent*>(
aAccessible->AsRemote()->Document()->Manager());
} if (auto element = bp->GetOwnerElement()) { if (auto doc = element->OwnerDoc()) { if (nsPresContext* presContext = doc->GetPresContext()) { return GetInstanceFor(presContext->PresShell());
}
} else {
MOZ_ASSERT_UNREACHABLE( "Browser parent's element does not have owner doc.");
}
}
}
nsViewManager* vm = aPresShell->GetViewManager(); if (!vm) { return nullptr;
}
nsCOMPtr<nsIWidget> rootWidget = vm->GetRootWidget(); // `rootWidget` can be one of several types. Here we make sure it is an // android nsWindow. if (RefPtr<nsWindow> window = nsWindow::From(rootWidget)) { return window->GetSessionAccessibility();
}
void SessionAccessibility::SendFocusEvent(Accessible* aAccessible) {
MOZ_ASSERT(NS_IsMainThread()); // Suppress focus events from about:blank pages. // This is important for tests. if (aAccessible->IsDoc() && aAccessible->ChildCount() == 0) { return;
}
void SessionAccessibility::SendWindowStateChangedEvent(
Accessible* aAccessible) {
MOZ_ASSERT(NS_IsMainThread()); // Suppress window state changed events from about:blank pages. // This is important for tests. if (aAccessible->IsDoc() && aAccessible->ChildCount() == 0) { return;
}
// Announcements should have the root as their source, so we ignore the // accessible of the event.
mSessionAccessibility->SendEvent(
java::sdk::AccessibilityEvent::TYPE_ANNOUNCEMENT, kNoID,
java::SessionAccessibility::CLASSNAME_WEBVIEW, eventInfo);
}
void SessionAccessibility::PopulateNodeInfo(
Accessible* aAccessible, mozilla::jni::Object::Param aNodeInfo) {
nsAutoString name;
aAccessible->Name(name);
nsAutoString textValue;
aAccessible->Value(textValue);
nsAutoString nodeID;
aAccessible->DOMNodeID(nodeID);
nsAutoString accDesc;
aAccessible->Description(accDesc);
uint64_t state = aAccessible->State();
LayoutDeviceIntRect bounds = aAccessible->Bounds();
uint8_t actionCount = aAccessible->ActionCount();
int32_t virtualViewID = AccessibleWrap::GetVirtualViewID(aAccessible);
Accessible* parent = virtualViewID != kNoID ? aAccessible->Parent() : nullptr;
int32_t parentID = parent ? AccessibleWrap::GetVirtualViewID(parent) : 0;
role role = aAccessible->Role(); if (role == roles::LINK && !(state & states::LINKED)) { // A link without the linked state (<a> with no href) shouldn't be presented // as a link.
role = roles::TEXT;
}
nsAutoString hint;
nsAutoString text;
nsAutoString description; if (state & states::EDITABLE) { // An editable field's name is populated in the hint.
hint.Assign(name);
text.Assign(textValue);
} else { if (role == roles::LINK || role == roles::HEADING) {
description.Assign(name);
} else {
text.Assign(name);
}
}
if (!accDesc.IsEmpty()) { if (!hint.IsEmpty()) { // If this is an editable, the description is concatenated with a // whitespace directly after the name.
hint.AppendLiteral(" ");
}
hint.Append(accDesc);
}
if ((state & states::REQUIRED) != 0) {
nsAutoString requiredString; if (LocalizeString(u"stateRequired"_ns, requiredString)) { if (!hint.IsEmpty()) { // If the hint is non-empty, concatenate with a comma for a brief pause.
hint.AppendLiteral(", ");
}
hint.Append(requiredString);
}
}
auto childCount = aAccessible->ChildCount();
nsTArray<int32_t> children(childCount); if (!nsAccUtils::MustPrune(aAccessible)) { for (uint32_t i = 0; i < childCount; i++) { auto child = aAccessible->ChildAt(i);
children.AppendElement(AccessibleWrap::GetVirtualViewID(child));
}
}
SessionAccessibility::IDMappingEntry&
SessionAccessibility::IDMappingEntry::operator=(Accessible* aAccessible) {
mInternalID = aAccessible->ID();
MOZ_ASSERT(!(mInternalID & IS_REMOTE), "First bit is used in accessible ID!"); if (aAccessible->IsRemote()) {
mInternalID |= IS_REMOTE;
}
if (mInternalID == IS_REMOTE) { returnstatic_cast<DocAccessibleParent*>(mDoc.get());
}
if (mInternalID & IS_REMOTE) { returnstatic_cast<DocAccessibleParent*>(mDoc.get())
->GetAccessible(mInternalID & ~IS_REMOTE);
}
Accessible* accessible = static_cast<LocalAccessible*>(mDoc.get())
->AsDoc()
->GetAccessibleByUniqueID(reinterpret_cast<void*>(mInternalID)); // If the accessible is retrievable from the DocAccessible, it can't be // defunct.
MOZ_ASSERT(!accessible->AsLocal()->IsDefunct());
return accessible;
}
void SessionAccessibility::RegisterAccessible(Accessible* aAccessible) { if (IPCAccessibilityActive()) { // Don't register accessible in content process. return;
}
nsAccessibilityService::GetAndroidMonitor().AssertCurrentThreadOwns();
RefPtr<SessionAccessibility> sessionAcc = GetInstanceFor(aAccessible); if (!sessionAcc) { return;
}
int32_t virtualViewID = kNoID; if (!isTopLevel) { if (sessionAcc->mIDToAccessibleMap.IsEmpty()) { // We expect there to already be at least one accessible // registered (the top-level one). If it isn't we are // probably in a shutdown process where it was already // unregistered. So we don't register this accessible. return;
} // Don't use the special "unset" value (0). while ((virtualViewID = sIDSet.GetID()) == kUnsetID) {
}
}
AccessibleWrap::SetVirtualViewID(aAccessible, virtualViewID);
Accessible* oldAcc = sessionAcc->mIDToAccessibleMap.Get(virtualViewID); if (oldAcc) { // About to overwrite mapping of registered accessible. This should // only happen when the registered accessible is a detached document.
MOZ_ASSERT(IsDetachedDoc(oldAcc), "ID already registered to non-detached document");
AccessibleWrap::SetVirtualViewID(oldAcc, kUnsetID);
}
RefPtr<SessionAccessibility> sessionAcc = GetInstanceFor(aAccessible); if (sessionAcc) {
Accessible* registeredAcc =
sessionAcc->mIDToAccessibleMap.Get(virtualViewID); if (registeredAcc != aAccessible) { // Attempting to unregister an accessible that is not mapped to // its virtual view ID. This probably means it is a detached document // and a more recent document overwrote its '-1' mapping. // We set its own virtual view ID to `kUnsetID` and return early.
MOZ_ASSERT(!registeredAcc || IsDetachedDoc(aAccessible), "Accessible is detached document");
AccessibleWrap::SetVirtualViewID(aAccessible, kUnsetID); return;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.