Bug 1768927 - Preload localized role strings and heading levels at init. r=Jamie

We can't use the StringBundle object off the main thread. We need to
pre-load all the strings we may use. This is a small set of roles. We
also need formatted heading levels, so we preload heading level 1 to 6.

Differential Revision: https://phabricator.services.mozilla.com/D146112
This commit is contained in:
Eitan Isaacson 2022-05-13 05:00:55 +00:00
parent 9e50a40691
commit dbd21dbf8b
4 changed files with 72 additions and 49 deletions

View File

@ -529,11 +529,13 @@ void AccessibleWrap::GetRoleDescription(role aRole, AccAttributes* aAttributes,
nsAString& aRoleDescription) {
if (aRole == roles::HEADING && aAttributes) {
// The heading level is an attribute, so we need that.
AutoTArray<nsString, 1> formatString;
if (aAttributes->GetAttribute(nsGkAtoms::level,
*formatString.AppendElement()) &&
LocalizeString("headingLevel", aRoleDescription, formatString)) {
return;
nsAutoString headingLevel;
if (aAttributes->GetAttribute(nsGkAtoms::level, headingLevel)) {
nsAutoString token(u"heading-");
token.Append(headingLevel);
if (LocalizeString(token, aRoleDescription)) {
return;
}
}
}
@ -542,8 +544,7 @@ void AccessibleWrap::GetRoleDescription(role aRole, AccAttributes* aAttributes,
if (aAttributes->GetAttribute(nsGkAtoms::xmlroles, xmlRoles)) {
nsWhitespaceTokenizer tokenizer(xmlRoles);
while (tokenizer.hasMoreTokens()) {
if (LocalizeString(NS_ConvertUTF16toUTF8(tokenizer.nextToken()).get(),
aRoleDescription)) {
if (LocalizeString(tokenizer.nextToken(), aRoleDescription)) {
return;
}
}
@ -551,7 +552,7 @@ void AccessibleWrap::GetRoleDescription(role aRole, AccAttributes* aAttributes,
}
GetAccService()->GetStringRole(aRole, aGeckoRole);
LocalizeString(NS_ConvertUTF16toUTF8(aGeckoRole).get(), aRoleDescription);
LocalizeString(aGeckoRole, aRoleDescription);
}
int32_t AccessibleWrap::AndroidClass(Accessible* aAccessible) {

View File

@ -19,11 +19,63 @@
using namespace mozilla;
using namespace mozilla::a11y;
static nsIStringBundle* sStringBundle;
static nsTHashMap<nsStringHashKey, nsString> sLocalizedStrings;
void a11y::PlatformInit() {}
void a11y::PlatformInit() {
nsresult rv = NS_OK;
nsCOMPtr<nsIStringBundleService> stringBundleService =
components::StringBundle::Service();
if (!stringBundleService) return;
void a11y::PlatformShutdown() { NS_IF_RELEASE(sStringBundle); }
nsCOMPtr<nsIStringBundle> stringBundle;
nsCOMPtr<nsIStringBundleService> sbs = components::StringBundle::Service();
if (NS_FAILED(rv)) {
NS_WARNING("Failed to get string bundle service");
return;
}
rv = sbs->CreateBundle(ROLE_STRINGS_URL, getter_AddRefs(stringBundle));
if (NS_FAILED(rv)) {
NS_WARNING("Failed to get string bundle");
return;
}
nsString localizedStr;
// Preload the state required localized string.
rv = stringBundle->GetStringFromName("stateRequired", localizedStr);
if (NS_SUCCEEDED(rv)) {
sLocalizedStrings.InsertOrUpdate(u"stateRequired"_ns, localizedStr);
}
// Preload heading level localized descriptions 1 thru 6.
for (int32_t level = 1; level <= 6; level++) {
nsAutoString token;
token.AppendPrintf("heading-%d", level);
nsAutoString formatString;
formatString.AppendInt(level);
AutoTArray<nsString, 1> formatParams;
formatParams.AppendElement(formatString);
rv = stringBundle->FormatStringFromName("headingLevel", formatParams,
localizedStr);
if (NS_SUCCEEDED(rv)) {
sLocalizedStrings.InsertOrUpdate(token, localizedStr);
}
}
// Preload any roles that have localized versions
#define ROLE(geckoRole, stringRole, atkRole, macRole, macSubrole, msaaRole, \
ia2Role, androidClass, nameRule) \
rv = stringBundle->GetStringFromName(stringRole, localizedStr); \
if (NS_SUCCEEDED(rv)) { \
sLocalizedStrings.InsertOrUpdate(u##stringRole##_ns, localizedStr); \
}
#include "RoleMap.h"
#undef ROLE
}
void a11y::PlatformShutdown() { sLocalizedStrings.Clear(); }
void a11y::ProxyCreated(RemoteAccessible* aProxy) {
SessionAccessibility::RegisterAccessible(aProxy);
@ -202,42 +254,14 @@ void a11y::ProxyBatch(RemoteAccessible* aDocument, const uint64_t aBatchType,
}
}
bool a11y::LocalizeString(const char* aToken, nsAString& aLocalized,
const nsTArray<nsString>& aFormatString) {
bool a11y::LocalizeString(const nsAString& aToken, nsAString& aLocalized) {
MOZ_ASSERT(XRE_IsParentProcess());
nsresult rv = NS_OK;
if (!sStringBundle) {
nsCOMPtr<nsIStringBundleService> sbs = components::StringBundle::Service();
if (NS_FAILED(rv)) {
NS_WARNING("Failed to get string bundle service");
return false;
}
nsCOMPtr<nsIStringBundle> sb;
rv = sbs->CreateBundle(ROLE_STRINGS_URL, getter_AddRefs(sb));
if (NS_FAILED(rv)) {
NS_WARNING("Failed to get string bundle");
return false;
}
sb.forget(&sStringBundle);
}
MOZ_ASSERT(sStringBundle);
if (aFormatString.Length()) {
rv = sStringBundle->FormatStringFromName(aToken, aFormatString, aLocalized);
if (NS_SUCCEEDED(rv)) {
return true;
}
auto str = sLocalizedStrings.Lookup(aToken);
if (str) {
aLocalized.Assign(*str);
} else {
rv = sStringBundle->GetStringFromName(aToken, aLocalized);
if (NS_SUCCEEDED(rv)) {
return true;
}
}
NS_WARNING("Failed to localize string");
aLocalized.AssignLiteral("");
return false;
return !!str;
}

View File

@ -719,7 +719,7 @@ mozilla::java::GeckoBundle::LocalRef SessionAccessibility::ToBundle(
if ((aState & states::REQUIRED) != 0) {
nsAutoString requiredString;
if (LocalizeString("stateRequired", 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(", ");
@ -899,7 +899,7 @@ void SessionAccessibility::PopulateNodeInfo(
if ((state & states::REQUIRED) != 0) {
nsAutoString requiredString;
if (LocalizeString("stateRequired", 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(", ");

View File

@ -141,9 +141,7 @@ void ProxyBatch(RemoteAccessible* aDocument, const uint64_t aBatchType,
const nsTArray<RemoteAccessible*>& aAccessibles,
const nsTArray<BatchData>& aData);
bool LocalizeString(
const char* aToken, nsAString& aLocalized,
const nsTArray<nsString>& aFormatString = nsTArray<nsString>());
bool LocalizeString(const nsAString& aToken, nsAString& aLocalized);
#endif
#ifdef MOZ_WIDGET_COCOA