Commit 22b27559 authored by Cliff Smolinsky's avatar Cliff Smolinsky Committed by Commit Bot

Improve accessibility for certificate viewer dialog

This change fixes multiple accessibilty issues with the certificate
viewer dialog, primarily with regards to screenreader support:
- The "Field Value" is never read in any way. This change makes it a
tab stop so that it can be read that way. It also adds aria-live so that
when the selected certificate field changes the updated field value is
read as well.
- The individual <tab>s in a <tabs> section are not individual tab stops
which makes it more difficult to understand what happens with a screen
reader. This also means that nothing is read when the selection changes.
This change makes the individual tabs tab stops, ensures the tab is
focused when it becomes selected, and sets the aria-selected property to
ensure selection state is read properly.
- The three different fields of information on the details tab (two trees
and the field value) were not labeled appropriately so while the content
was read it wasn't clear what the information represented. This change
adds proper labeling.
- When an item in a tree was read, its level in the tree was always off-
by-one. This change fixes that by properly labeling the root of the tree
as a tree instead of a group.
- The gray color used for information text on the general tab didn't
meet contrast requirements so this change make the text a little darker.
- Additional changes to add appropriate role and aria-* properties to
various elements for proper identification.

Bug: 971843
Change-Id: I677a01fa785900c66939d3b5263c6e5914fc8482
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1651513Reviewed-by: default avatarHector Carmona <hcarmona@chromium.org>
Commit-Queue: Cliff Smolinsky <cliffsmo@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#673387}
parent a7787963
......@@ -56,7 +56,7 @@ h3 {
#usages,
.groups > div > div {
color: #787878;
color: #616161;
line-height: 18px;
padding-inline-start: 20px;
}
......
<!doctype html>
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
<meta charset="utf-8">
......@@ -19,21 +19,25 @@
</head>
<body>
<tabbox id="tabbox">
<tabs id="tabs" class="new-style-tabs">
<tab>$i18n{general}</tab>
<tab>$i18n{details}</tab>
<tabs id="tabs" class="new-style-tabs" role="tablist">
<tab id="general-tab" role="tab" aria-controls="general" tabindex="0">
$i18n{general}
</tab>
<tab id="details-tab" role="tab" aria-controls="details">
$i18n{details}
</tab>
</tabs>
<tabpanels id="tabpanels" class="new-style-tabs">
<!-- General -->
<tabpanel id="general">
<tabpanel id="general" aria-labelledby="general-tab">
<!-- Usages -->
<h3 id="usages-title">$i18n{usages}</h3>
<h3 id="usages-title" role="group">$i18n{usages}</h3>
<div id="usages"></div>
<div class="groups">
<!-- Issued to -->
<div>
<h3>$i18n{issuedTo}</h3>
<h3 role="group">$i18n{issuedTo}</h3>
</div>
<div>
<div class="attribute">$i18n{cn}</div>
......@@ -50,7 +54,7 @@
<!-- Issued by -->
<div>
<h3>$i18n{issuedBy}</h3>
<h3 role="group">$i18n{issuedBy}</h3>
</div>
<div>
<div class="attribute">$i18n{cn}</div>
......@@ -67,7 +71,7 @@
<!-- Validity -->
<div>
<h3>$i18n{validity}</h3>
<h3 role="group">$i18n{validity}</h3>
</div>
<div>
<div class="attribute">$i18n{issuedOn}</div>
......@@ -80,7 +84,7 @@
<!-- Fingerprints -->
<div>
<h3>$i18n{fingerprints}</h3>
<h3 role="group">$i18n{fingerprints}</h3>
</div>
<div>
<div class="attribute">$i18n{sha256}</div>
......@@ -94,20 +98,26 @@
</tabpanel>
<!-- Details -->
<tabpanel>
<tabpanel id="details" aria-labelledby="details-tab">
<div id="hierarchy-section" class="vertical-box">
<h3>$i18n{hierarchy}</h3>
<h3 id="hierarchy-label" role="group">$i18n{hierarchy}</h3>
<tree id="hierarchy" class="section-contents"
icon-visibility='hidden'></tree>
aria-labelledby="hierarchy-label"
icon-visibility='hidden'></tree>
</div>
<div id="cert-fields-section" class="vertical-box">
<h3>$i18n{certFields}</h3>
<h3 id="cert-fields-label" role="group">$i18n{certFields}</h3>
<tree id="cert-fields" class="section-contents"
icon-visibility='hidden'></tree>
aria-labelledby="cert-fields-label"
icon-visibility='hidden'></tree>
</div>
<div id="cert-field-value-section" class="vertical-box">
<h3>$i18n{certFieldVal}</h3>
<div id="cert-field-value" class="section-contents"></div>
<h3 id="cert-field-value-label" role="group">
$i18n{certFieldVal}
</h3>
<div id="cert-field-value" class="section-contents" tabindex="0"
aria-live="polite" aria-atomic="true" aria-readonly="true"
aria-labelledby="cert-field-value-label" role="textbox"></div>
<div>
<button id="export">$i18n{export}</button>
</div>
......
......@@ -57,7 +57,20 @@ cr.define('cr.ui', function() {
if (element) {
let i;
for (i = 0; child = element.children[i]; i++) {
child.selected = i == selectedIndex;
const isSelected = i == selectedIndex;
child.selected = isSelected;
// Update tabIndex for a11y
child.setAttribute('tabindex', isSelected ? 0 : -1);
// Update aria-selected attribute for a11y
const firstSelection = !child.hasAttribute('aria-selected');
child.setAttribute('aria-selected', isSelected);
// Update focus, but don't override initial focus.
if (isSelected && !firstSelection) {
child.focus();
}
}
}
......@@ -122,8 +135,6 @@ cr.define('cr.ui', function() {
decorate: function() {
decorateChildren.call(this);
// Make the Tabs element focusable.
this.tabIndex = 0;
this.addEventListener('keydown', this.handleKeyDown_.bind(this));
// Get (and initializes a focus outline manager.
......
......@@ -60,7 +60,7 @@ cr.define('cr.ui', function() {
this.addEventListener('keydown', this.handleKeyDown);
if (!this.hasAttribute('role')) {
this.setAttribute('role', 'group');
this.setAttribute('role', 'tree');
}
},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment