0

Chromium Task Manager - TableView Accessibility(part 4)

This CL format the ICU syntax of the IDS string for table rows. Also use
ListFormatter to format the header name and the task name for task
group.

With this change. The AX name for table header for macOS would be, col1,
col2, col3 and col4 the row name for task group would be . col1, col2,
col3 and col4. Another task in the same task group: taskA col1, col2,
col3 and col4. Other 3 tasks in the same task group: taskA, taskB and
taskC

Screenshot demo:
header -
https://screenshot.googleplex.com/8sLV9Xvp4ptUZvn

task group -
https://screenshot.googleplex.com/5wNACdTACp2oCgo
https://screenshot.googleplex.com/84ojrjUy3Ytesqm

Bug: 396213873
Change-Id: I9415379a18670f97e11ef5ae42302546c2707a64
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6334691
Reviewed-by: Peter Kasting <pkasting@chromium.org>
Reviewed-by: Michael Wojcicka <mwoj@google.com>
Commit-Queue: Zhengzheng Liu <zhzhliu@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1432462}
This commit is contained in:
Zhengzheng Liu
2025-03-13 17:16:18 -07:00
committed by Chromium LUCI CQ
parent 6445fbe646
commit 1d31234adb
6 changed files with 86 additions and 8 deletions

@ -4944,7 +4944,11 @@ are declared in tools/grit/grit_args.gni.
<ph name="NUM_HANDLES">$1<ex>300</ex></ph> (<ph name="NUM_KILOBYTES_LIVE">$2<ex>500</ex></ph> peak)
</message>
<message name="IDS_TASK_MANAGER_TASK_GROUP_CONNECT_TEXT" desc="The text used to connect tasks in the same task group for accessibility features. [ICU_Syntax]">
{NUM_TASKS, plural, =1 {<ph name="TASK_ROW">{TASK_ROW}<ex>MyTask</ex></ph>} other {<ph name="TASK_ROW">{TASK_ROW}<ex>MyTask</ex></ph>. Other <ph name="OTHER_TASK_NUM">{OTHER_TASK_NUM}<ex>2</ex></ph> tasks in the same task group: <ph name="OTHER_TASKS">{OTHER_TASKS}<ex>TaskA TaskB</ex></ph>}}
{NUM_TASKS, plural,
=0 {<ph name="TASK_ROW">{TASK_ROW}<ex>MyTask</ex></ph>}
=1 {<ph name="TASK_ROW">{TASK_ROW}<ex>MyTask</ex></ph>. Another task in the same task group: <ph name="OTHER_TASKS">{OTHER_TASKS}<ex>TaskA</ex></ph>}
other {<ph name="TASK_ROW">{TASK_ROW}<ex>MyTask</ex></ph>. Other # tasks in the same task group: <ph name="OTHER_TASKS">{OTHER_TASKS}<ex>TaskA, TaskB, and TaskC</ex></ph>}
}
</message>
<message name="IDS_TASK_MANAGER_WEB_BROWSER_CELL_TEXT" desc="The text of the web browser process row">
Browser

@ -1 +1 @@
2f2eeb1e1832bc4a02d45522418b098f4ef6b26b
17c4bc1d9cf5e3644df73df5110178c8875e436a

@ -22,6 +22,8 @@
#include "base/i18n/rtl.h"
#include "base/i18n/string_search.h"
#include "base/i18n/time_formatting.h"
#include "base/i18n/unicodestring.h"
#include "base/numerics/safe_conversions.h"
#include "base/process/process_handle.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@ -42,6 +44,8 @@
#include "components/nacl/common/nacl_switches.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "content/public/common/result_codes.h"
#include "third_party/icu/source/common/unicode/utypes.h"
#include "third_party/icu/source/i18n/unicode/listformatter.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/image_model.h"
#include "ui/base/models/table_model_observer.h"
@ -723,7 +727,7 @@ std::u16string TaskManagerTableModel::GetAXNameForHeader(
}
CHECK(!visible_column_titles.empty());
return base::JoinString(visible_column_titles, u" ");
return FormatListToString(visible_column_titles);
}
std::u16string TaskManagerTableModel::GetAXNameForRow(
@ -779,13 +783,35 @@ std::u16string TaskManagerTableModel::GetAXNameForRow(
}
}
const int other_tasks_size = static_cast<int>(other_task_titles.size());
return base::i18n::MessageFormatter::FormatWithNamedArgs(
l10n_util::GetStringUTF16(IDS_TASK_MANAGER_TASK_GROUP_CONNECT_TEXT),
"NUM_TASKS", other_tasks_size + 1, "TASK_ROW",
base::JoinString(column_names, u" "), "OTHER_TASK_NUM", other_tasks_size,
"OTHER_TASKS", base::JoinString(other_task_titles, u" "));
"NUM_TASKS", base::checked_cast<int>(other_task_titles.size()),
"TASK_ROW", FormatListToString(column_names), "OTHER_TASKS",
FormatListToString(other_task_titles));
}
std::u16string TaskManagerTableModel::FormatListToString(
base::span<const std::u16string> items) {
if (items.empty()) {
return std::u16string();
}
std::vector<icu::UnicodeString> strings;
strings.reserve(items.size());
for (const auto& item : items) {
strings.emplace_back(item.data(), item.size());
}
UErrorCode status = U_ZERO_ERROR;
const auto formatter =
base::WrapUnique(icu::ListFormatter::createInstance(status));
CHECK(U_SUCCESS(status));
icu::UnicodeString formatted;
formatter->format(strings.data(), strings.size(), formatted, status);
CHECK(U_SUCCESS(status));
return base::i18n::UnicodeStringToString16(formatted);
}
void TaskManagerTableModel::GetRowsGroupRange(size_t row_index,

@ -99,6 +99,9 @@ class TaskManagerTableModel : public TaskManagerObserver,
size_t row,
const std::vector<int>& visible_column_ids) override;
static std::u16string FormatListToString(
base::span<const std::u16string> items);
void FilterTaskList(TaskIdList& tasks);
// task_manager::TaskManagerObserver:

@ -0,0 +1,44 @@
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/task_manager/task_manager_table_model.h"
#include <string>
#include <string_view>
#include <vector>
#include "testing/gtest/include/gtest/gtest.h"
using TaskManagerTableModelTest = testing::Test;
namespace {
bool ContainsSubstringsInOrder(std::u16string_view text,
const std::vector<std::u16string>& substrings) {
for (const auto& substring : substrings) {
size_t found_pos = text.find(substring);
if (found_pos == std::u16string_view::npos) {
return false;
}
text.remove_prefix(found_pos + substring.length());
}
return true;
}
} // namespace
TEST_F(TaskManagerTableModelTest, FormatListToString) {
std::vector<std::u16string> tasks;
EXPECT_EQ(task_manager::TaskManagerTableModel::FormatListToString(tasks),
std::u16string());
tasks.push_back(u"task1");
EXPECT_TRUE(ContainsSubstringsInOrder(
task_manager::TaskManagerTableModel::FormatListToString(tasks), tasks));
tasks.push_back(u"task2");
EXPECT_TRUE(ContainsSubstringsInOrder(
task_manager::TaskManagerTableModel::FormatListToString(tasks), tasks));
tasks.push_back(u"task3");
EXPECT_TRUE(ContainsSubstringsInOrder(
task_manager::TaskManagerTableModel::FormatListToString(tasks), tasks));
}

@ -6260,6 +6260,7 @@ test("unit_tests") {
"../browser/ui/passwords/password_cross_domain_confirmation_popup_controller_impl_unittest.cc",
"../browser/ui/plus_addresses/plus_address_creation_controller_desktop_unittest.cc",
"../browser/ui/plus_addresses/plus_address_menu_model_unittest.cc",
"../browser/ui/task_manager/task_manager_table_model_unittest.cc",
"../browser/ui/user_education/recent_session_policy_unittest.cc",
"../browser/ui/webui/profile_internals/profile_internals_handler_unittest.cc",
"../browser/user_education/browser_user_education_storage_service_unittest.cc",