Commit 43be2077 authored by Kuo Jen Wei's avatar Kuo Jen Wei Committed by Commit Bot

CCA: Prevent chromevox navigate to preview video element

The preview video element is not interactable with chromevox. This CL
prevent chromevox navigate to preview by creating preview video from
template with aria-hide=true.

Bug: 1135052
Test: Manually with chromevox
Test: tast run <DUT> "camera.CCAUI*"

Change-Id: I1dfc87b564dd1db119c10643b587fa254470493a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2454913
Auto-Submit: Inker Kuo <inker@chromium.org>
Commit-Queue: Shik Chen <shik@chromium.org>
Reviewed-by: default avatarShik Chen <shik@chromium.org>
Cr-Commit-Position: refs/heads/master@{#814585}
parent e9f7b295
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import {assertInstanceof} from './chrome_util.js'; import {assertInstanceof} from './chrome_util.js';
import {setupI18nElements} from './util.js';
// Disables eslint check for closure compiler constructor type. // Disables eslint check for closure compiler constructor type.
/* eslint-disable valid-jsdoc */ /* eslint-disable valid-jsdoc */
...@@ -10,7 +11,7 @@ import {assertInstanceof} from './chrome_util.js'; ...@@ -10,7 +11,7 @@ import {assertInstanceof} from './chrome_util.js';
/** /**
* Gets an element matching css selector under the target element and checks its * Gets an element matching css selector under the target element and checks its
* type. * type.
* @param {(!HTMLElement|!HTMLDocument)} target * @param {!Node} target
* @param {string} selector * @param {string} selector
* @param {function(new: T, ...)} type A user-defined constructor. * @param {function(new: T, ...)} type A user-defined constructor.
* @return {T} * @return {T}
...@@ -23,7 +24,7 @@ export function getFrom(target, selector, type) { ...@@ -23,7 +24,7 @@ export function getFrom(target, selector, type) {
/** /**
* Gets all elements matching css selector under the target element and asserts * Gets all elements matching css selector under the target element and asserts
* their type to be specific type. * their type to be specific type.
* @param {(!HTMLElement|!HTMLDocument)} target * @param {!Node} target
* @param {string} selector * @param {string} selector
* @param {function(new: T, ...)} type A user-defined constructor. * @param {function(new: T, ...)} type A user-defined constructor.
* @return {!NodeList<T>} * @return {!NodeList<T>}
...@@ -60,4 +61,16 @@ export function getAll(selector, type) { ...@@ -60,4 +61,16 @@ export function getAll(selector, type) {
return getAllFrom(document, selector, type); return getAllFrom(document, selector, type);
} }
/**
* Instantiates template with the target selector.
* @param {string} selector
* @return {!Node}
*/
export function instantiateTemplate(selector) {
const tpl = get(selector, HTMLTemplateElement);
const node = document.importNode(tpl.content, true);
setupI18nElements(node);
return node;
}
/* eslint-enable valid-jsdoc */ /* eslint-enable valid-jsdoc */
...@@ -290,7 +290,8 @@ export function openHelp() { ...@@ -290,7 +290,8 @@ export function openHelp() {
/** /**
* Sets up i18n messages on DOM subtree by i18n attributes. * Sets up i18n messages on DOM subtree by i18n attributes.
* @param {!HTMLElement} rootElement Root of DOM subtree to be set up with. * @param {!Node} rootElement Root of DOM subtree to be set up
* with.
*/ */
export function setupI18nElements(rootElement) { export function setupI18nElements(rootElement) {
const getElements = (attr) => rootElement.querySelectorAll('[' + attr + ']'); const getElements = (attr) => rootElement.querySelectorAll('[' + attr + ']');
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
// found in the LICENSE file. // found in the LICENSE file.
import {browserProxy} from '../../browser_proxy/browser_proxy.js'; import {browserProxy} from '../../browser_proxy/browser_proxy.js';
import {assertInstanceof} from '../../chrome_util.js';
import * as dom from '../../dom.js'; import * as dom from '../../dom.js';
import {DeviceOperator, parseMetadata} from '../../mojo/device_operator.js'; import {DeviceOperator, parseMetadata} from '../../mojo/device_operator.js';
import * as nav from '../../nav.js'; import * as nav from '../../nav.js';
...@@ -109,11 +108,8 @@ export class Preview { ...@@ -109,11 +108,8 @@ export class Preview {
* @return {!Promise} Promise for the operation. * @return {!Promise} Promise for the operation.
*/ */
async setSource_(stream) { async setSource_(stream) {
const video = const node = dom.instantiateTemplate('#preview-video-template');
assertInstanceof(document.createElement('video'), HTMLVideoElement); const video = dom.getFrom(node, 'video', HTMLVideoElement);
video.id = 'preview-video';
video.classList = this.video_.classList;
video.muted = true; // Mute to avoid echo from the captured audio.
await new Promise((resolve) => { await new Promise((resolve) => {
const handler = () => { const handler = () => {
video.removeEventListener('canplay', handler); video.removeEventListener('canplay', handler);
...@@ -123,7 +119,7 @@ export class Preview { ...@@ -123,7 +119,7 @@ export class Preview {
video.srcObject = stream; video.srcObject = stream;
}); });
await video.play(); await video.play();
this.video_.parentElement.replaceChild(video, this.video_); this.video_.parentElement.replaceChild(node, this.video_);
this.video_.removeAttribute('srcObject'); this.video_.removeAttribute('srcObject');
this.video_.load(); this.video_.load();
this.video_ = video; this.video_ = video;
......
...@@ -225,20 +225,6 @@ export class ResolutionSettings extends BaseSettings { ...@@ -225,20 +225,6 @@ export class ResolutionSettings extends BaseSettings {
*/ */
this.backVideoItem_ = dom.get('#settings-back-videores', HTMLElement); this.backVideoItem_ = dom.get('#settings-back-videores', HTMLElement);
/**
* @type {!HTMLTemplateElement}
* @private
*/
this.resItemTempl_ =
dom.get('#resolution-item-template', HTMLTemplateElement);
/**
* @type {!HTMLTemplateElement}
* @private
*/
this.extcamItemTempl_ =
dom.get('#extcam-resolution-item-template', HTMLTemplateElement);
/** /**
* Device setting of front camera. Null if no front camera. * Device setting of front camera. Null if no front camera.
* @type {?DeviceSetting} * @type {?DeviceSetting}
...@@ -454,9 +440,8 @@ export class ResolutionSettings extends BaseSettings { ...@@ -454,9 +440,8 @@ export class ResolutionSettings extends BaseSettings {
let /** !HTMLElement */ photoItem; let /** !HTMLElement */ photoItem;
let /** !HTMLElement */ videoItem; let /** !HTMLElement */ videoItem;
if (deviceId !== focusedId) { if (deviceId !== focusedId) {
const extItem = /** @type {!HTMLElement} */ ( const extItem =
document.importNode(this.extcamItemTempl_.content, true)); dom.instantiateTemplate('#extcam-resolution-item-template');
util.setupI18nElements(extItem);
[titleItem, photoItem, videoItem] = [titleItem, photoItem, videoItem] =
dom.getAllFrom(extItem, '.menu-item', HTMLElement); dom.getAllFrom(extItem, '.menu-item', HTMLElement);
...@@ -625,8 +610,7 @@ export class ResolutionSettings extends BaseSettings { ...@@ -625,8 +610,7 @@ export class ResolutionSettings extends BaseSettings {
.forEach((element) => element.parentNode.removeChild(element)); .forEach((element) => element.parentNode.removeChild(element));
resolutions.forEach((r) => { resolutions.forEach((r) => {
const item = /** @type {!HTMLElement} */ ( const item = dom.instantiateTemplate('#resolution-item-template');
document.importNode(this.resItemTempl_.content, true));
const label = dom.getFrom(item, 'label', HTMLLabelElement); const label = dom.getFrom(item, 'label', HTMLLabelElement);
util.setInkdropEffect(label); util.setInkdropEffect(label);
const input = dom.getFrom(item, 'input', HTMLInputElement); const input = dom.getFrom(item, 'input', HTMLInputElement);
......
...@@ -406,6 +406,10 @@ ...@@ -406,6 +406,10 @@
<audio id="sound-rec-end" src="/sounds/record_end.ogg" data-timeout="450"> <audio id="sound-rec-end" src="/sounds/record_end.ogg" data-timeout="450">
<audio id="sound-rec-pause" src="/sounds/record_pause.ogg" <audio id="sound-rec-pause" src="/sounds/record_pause.ogg"
data-timeout="500"> data-timeout="500">
<template id="preview-video-template">
<video id="preview-video" class="preview-content" aria-hidden="true"
muted></video>
</template>
<template id="resolution-item-template"> <template id="resolution-item-template">
<label class="menu-item circle resolution-option"> <label class="menu-item circle resolution-option">
<input class="icon" type="radio" tabindex="0"> <input class="icon" type="radio" tabindex="0">
......
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