Commit 2b424064 authored by Akihiro Ota's avatar Akihiro Ota Committed by Commit Bot

ChromeVox OOBE Tutorial

This change:
1. Fills in content for the tutorial given in the OOBE.
2. Automatically opens the OOBE tutorial if ChromeVox is started from
the OOBE. Only do this if the
--enable-experimental-accessibility-chromevox-tutorial flag is enabled.
3. Adds a Panel method for creating the interactive tutorial. The logic
for this function existed prior to this change; we add this method for
better cleanliness and readability.

Bug: 1075752
Change-Id: I3aaefb2a934cde078747bfee105c1427af305400
AX-Relnotes: N/A
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2330048
Commit-Queue: Akihiro Ota <akihiroota@chromium.org>
Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796205}
parent 81b4743d
...@@ -183,6 +183,24 @@ Background = class extends ChromeVoxState { ...@@ -183,6 +183,24 @@ Background = class extends ChromeVoxState {
onTtsInterrupted() {} onTtsInterrupted() {}
}; };
new ProgressPlayer(); new ProgressPlayer();
chrome.commandLinePrivate.hasSwitch(
'enable-experimental-accessibility-chromevox-tutorial', (enabled) => {
if (!enabled) {
return;
}
chrome.loginState.getSessionState((sessionState) => {
// If starting ChromeVox from OOBE, start the ChromeVox tutorial.
// Use a timeout to allow ChromeVox to initialize first.
if (sessionState ===
chrome.loginState.SessionState.IN_OOBE_SCREEN) {
setTimeout(() => {
(new PanelCommand(PanelCommandType.TUTORIAL)).send();
}, 1000);
}
});
});
} }
/** /**
......
...@@ -101,7 +101,6 @@ h1 { ...@@ -101,7 +101,6 @@ h1 {
hidden$="[[ shouldHideMainMenu(activeScreen) ]]"> hidden$="[[ shouldHideMainMenu(activeScreen) ]]">
<h1 id="mainMenuHeader" tabindex="-1">[[ chooseYourExperience ]]</h1> <h1 id="mainMenuHeader" tabindex="-1">[[ chooseYourExperience ]]</h1>
<div id="mainMenuButtons"> <div id="mainMenuButtons">
<cr-button id="oobeButton" on-click="chooseCurriculum">OOBE</cr-button>
<cr-button id="newUserButton" on-click="chooseCurriculum"> <cr-button id="newUserButton" on-click="chooseCurriculum">
[[ newUser ]] [[ newUser ]]
</cr-button> </cr-button>
...@@ -125,8 +124,8 @@ h1 { ...@@ -125,8 +124,8 @@ h1 {
hidden$="[[ shouldHideLessonContainer(activeScreen) ]]"> hidden$="[[ shouldHideLessonContainer(activeScreen) ]]">
<!-- Use lessonData object to create all lessons --> <!-- Use lessonData object to create all lessons -->
<template is="dom-repeat" items="[[ lessonData ]]" as="lesson" <template id="lessonTemplate" is="dom-repeat" items="[[ lessonData ]]"
index-as="index"> as="lesson" index-as="index">
<tutorial-lesson <tutorial-lesson
lesson-num="[[ index ]]" lesson-num="[[ index ]]"
title="[[ lesson.title ]]" title="[[ lesson.title ]]"
...@@ -161,13 +160,18 @@ h1 { ...@@ -161,13 +160,18 @@ h1 {
[[ nextLesson ]] [[ nextLesson ]]
</cr-button> </cr-button>
<cr-button on-click="showLessonMenu" <cr-button on-click="showLessonMenu"
hidden$="[[ !shouldHideLessonMenu(activeScreen) ]]"> hidden$="[[ shouldHideLessonMenuButton(activeScreen) ]]">
[[ lessonMenu ]] [[ lessonMenu ]]
</cr-button> </cr-button>
<cr-button on-click="showMainMenu" <cr-button on-click="showMainMenu"
hidden$="[[ !shouldHideMainMenu(activeScreen) ]]"> hidden$="[[ shouldHideMainMenuButton(activeScreen) ]]">
[[ mainMenu ]] [[ mainMenu ]]
</cr-button> </cr-button>
<cr-button on-click="showFirstLesson"
hidden$="[[
shouldHideRestartBasicOrientationButton(activeLessonIndex) ]]">
[[ restartBasicOrientation ]]
</cr-button>
<cr-button on-click="exit">[[ exitTutorial ]]</cr-button> <cr-button on-click="exit">[[ exitTutorial ]]</cr-button>
</div> </div>
</div> </div>
......
...@@ -84,6 +84,10 @@ export const TutorialLesson = Polymer({ ...@@ -84,6 +84,10 @@ export const TutorialLesson = Polymer({
'A lesson must have an element which specifies tabindex.'); 'A lesson must have an element which specifies tabindex.');
} }
focus.focus(); focus.focus();
if (!focus.isEqualNode(this.shadowRoot.activeElement)) {
// Call show() again if we weren't able to focus the target element.
setTimeout(this.show.bind(this), 500);
}
}, },
/** @private */ /** @private */
......
...@@ -189,7 +189,6 @@ Panel = class { ...@@ -189,7 +189,6 @@ Panel = class {
/** @private {boolean} */ /** @private {boolean} */
Panel.iTutorialEnabled_ = false; Panel.iTutorialEnabled_ = false;
chrome.commandLinePrivate.hasSwitch( chrome.commandLinePrivate.hasSwitch(
'enable-experimental-accessibility-chromevox-tutorial', (enabled) => { 'enable-experimental-accessibility-chromevox-tutorial', (enabled) => {
Panel.iTutorialEnabled_ = enabled; Panel.iTutorialEnabled_ = enabled;
...@@ -1136,64 +1135,23 @@ Panel = class { ...@@ -1136,64 +1135,23 @@ Panel = class {
* @param {string=} opt_page Show a specific page. * @param {string=} opt_page Show a specific page.
*/ */
static onTutorial(opt_page) { static onTutorial(opt_page) {
// Change the url fragment to 'fullscreen', which signals the native
// host code to make the window fullscreen, revealing the menus.
if (Panel.iTutorialEnabled_) { if (Panel.iTutorialEnabled_) {
if ($('i-tutorial') === null) { if (!$('i-tutorial')) {
// Load resources if this is the first time opening the tutorial. const curriculum = Panel.sessionState ===
const tutorialScript = document.createElement('script'); chrome.loginState.SessionState.IN_OOBE_SCREEN ?
tutorialScript.src = '../i_tutorial/i_tutorial.js'; 'oobe' :
tutorialScript.setAttribute('type', 'module'); null;
const lessonScript = document.createElement('script'); Panel.createITutorial(curriculum);
lessonScript.src = '../i_tutorial/tutorial_lesson.js';
lessonScript.setAttribute('type', 'module');
document.body.appendChild(tutorialScript);
document.body.appendChild(lessonScript);
// Create tutorial container and element.
const tutorialContainer = document.createElement('div');
tutorialContainer.setAttribute('id', 'i-tutorial-container');
tutorialContainer.hidden = true;
const tutorialElement = document.createElement('i-tutorial');
tutorialElement.setAttribute('id', 'i-tutorial');
tutorialContainer.appendChild(tutorialElement);
document.body.appendChild(tutorialContainer);
Panel.iTutorial = tutorialElement;
// Add listeners. These are custom events fired from custom components.
$('i-tutorial').addEventListener('closetutorial', (evt) => {
// Ensure UserActionMonitor is destroyed before closing tutorial.
const background =
chrome.extension
.getBackgroundPage()['ChromeVoxState']['instance'];
background.destroyUserActionMonitor();
Panel.onCloseTutorial();
});
$('i-tutorial').addEventListener('requestspeech', (evt) => {
const text = evt.detail.text;
const background = chrome.extension.getBackgroundPage();
const cvox = background['ChromeVox'];
cvox.tts.speak(
text, background.QueueMode.FLUSH, {'doNotInterrupt': true});
});
$('i-tutorial').addEventListener('startinteractivemode', (evt) => {
const actions = evt.detail.actions;
const background =
chrome.extension
.getBackgroundPage()['ChromeVoxState']['instance'];
background.createUserActionMonitor(actions, () => {
background.destroyUserActionMonitor();
Panel.iTutorial.showNextLesson();
});
});
} }
Panel.setMode(Panel.Mode.FULLSCREEN_I_TUTORIAL); Panel.setMode(Panel.Mode.FULLSCREEN_I_TUTORIAL);
if (Panel.iTutorial.show) {
Panel.iTutorial.show();
}
return; return;
} }
Panel.setMode(Panel.Mode.FULLSCREEN_TUTORIAL); Panel.setMode(Panel.Mode.FULLSCREEN_TUTORIAL);
switch (opt_page) { switch (opt_page) {
case 'updateNotes': case 'updateNotes':
Panel.tutorial_.updateNotes(); Panel.tutorial_.updateNotes();
...@@ -1203,6 +1161,64 @@ Panel = class { ...@@ -1203,6 +1161,64 @@ Panel = class {
} }
} }
/**
* Creates an <i-tutorial> element and adds it to the dom.
* @param {(string|null)} curriculum
*/
static createITutorial(curriculum) {
const tutorialScript = document.createElement('script');
tutorialScript.src = '../i_tutorial/i_tutorial.js';
tutorialScript.setAttribute('type', 'module');
const lessonScript = document.createElement('script');
lessonScript.src = '../i_tutorial/tutorial_lesson.js';
lessonScript.setAttribute('type', 'module');
document.body.appendChild(tutorialScript);
document.body.appendChild(lessonScript);
// Create tutorial container and element.
const tutorialContainer = document.createElement('div');
tutorialContainer.setAttribute('id', 'i-tutorial-container');
tutorialContainer.hidden = true;
const tutorialElement = document.createElement('i-tutorial');
tutorialElement.setAttribute('id', 'i-tutorial');
if (curriculum) {
tutorialElement.curriculum = curriculum;
}
tutorialContainer.appendChild(tutorialElement);
document.body.appendChild(tutorialContainer);
Panel.iTutorial = tutorialElement;
// Add listeners. These are custom events fired from custom components.
$('i-tutorial').addEventListener('closetutorial', (evt) => {
// Ensure UserActionMonitor is destroyed before closing tutorial.
const background =
chrome.extension.getBackgroundPage()['ChromeVoxState']['instance'];
background.destroyUserActionMonitor();
Panel.onCloseTutorial();
});
$('i-tutorial').addEventListener('requestspeech', (evt) => {
const text = evt.detail.text;
const background = chrome.extension.getBackgroundPage();
const cvox = background['ChromeVox'];
cvox.tts.speak(
text, background.QueueMode.INTERJECT, {'doNotInterrupt': true});
});
$('i-tutorial').addEventListener('startinteractivemode', (evt) => {
const actions = evt.detail.actions;
const background =
chrome.extension.getBackgroundPage()['ChromeVoxState']['instance'];
background.createUserActionMonitor(actions, () => {
background.destroyUserActionMonitor();
Panel.iTutorial.showNextLesson();
});
});
$('i-tutorial').addEventListener('stopinteractivemode', (evt) => {
const background =
chrome.extension.getBackgroundPage()['ChromeVoxState']['instance'];
background.destroyUserActionMonitor();
});
}
/** /**
* Move to the next page in the tutorial. * Move to the next page in the tutorial.
*/ */
......
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