| Index: chrome/browser/resources/hotword_audio_verification/flow.js
|
| diff --git a/chrome/browser/resources/hotword_audio_verification/flow.js b/chrome/browser/resources/hotword_audio_verification/flow.js
|
| index e37bc881bf2eb75050f31979fc6bac3108795fcd..7a3a947fa75dad3092a58ef2d91b0cb9a039cec3 100644
|
| --- a/chrome/browser/resources/hotword_audio_verification/flow.js
|
| +++ b/chrome/browser/resources/hotword_audio_verification/flow.js
|
| @@ -23,6 +23,17 @@
|
| ];
|
|
|
| /**
|
| + * The launch mode. This enum needs to be kept in sync with that of
|
| + * the same name in hotword_service.h.
|
| + * @enum {number}
|
| + */
|
| + var LaunchMode = {
|
| + HOTWORD_ONLY: 0,
|
| + HOTWORD_AND_AUDIO_HISTORY: 1,
|
| + RETRAIN: 2
|
| + };
|
| +
|
| + /**
|
| * Class to control the page flow of the always-on hotword and
|
| * Audio History opt-in process.
|
| * @constructor
|
| @@ -30,6 +41,24 @@
|
| function Flow() {
|
| this.currentStepIndex_ = -1;
|
| this.currentFlow_ = [];
|
| +
|
| + /**
|
| + * Whether this flow is currently in the process of training a voice model.
|
| + * @private {LaunchMode}
|
| + */
|
| + this.launchMode_ = LaunchMode.HOTWORD_AND_AUDIO_HISTORY;
|
| +
|
| + /**
|
| + * Whether this flow is currently in the process of training a voice model.
|
| + * @private {boolean}
|
| + */
|
| + this.training_ = false;
|
| +
|
| + /**
|
| + * Prefix of the element ids for the page that is currently training.
|
| + * @private {string}
|
| + */
|
| + this.trainingPagePrefix_ = '';
|
| }
|
|
|
| /**
|
| @@ -49,17 +78,127 @@
|
| chrome.hotwordPrivate.getLaunchState(this.startFlowForMode_.bind(this));
|
| };
|
|
|
| + /**
|
| + * Starts the training process.
|
| + */
|
| + Flow.prototype.startTraining = function() {
|
| + // Don't start a training session if one already exists.
|
| + if (this.training_)
|
| + return;
|
| +
|
| + this.training_ = true;
|
| + if (this.launchMode_ == LaunchMode.HOTWORD_ONLY ||
|
| + this.launchMode_ == LaunchMode.RETRAIN) {
|
| + this.trainingPagePrefix_ = 'hotword-only';
|
| + } else if (this.launchMode_ == LaunchMode.HOTWORD_AND_AUDIO_HISTORY) {
|
| + this.trainingPagePrefix_ = 'speech-training';
|
| + }
|
| +
|
| + if (chrome.hotwordPrivate.onHotwordTriggered) {
|
| + chrome.hotwordPrivate.onHotwordTriggered.addListener(
|
| + this.handleHotwordTrigger_.bind(this));
|
| + }
|
| + if (chrome.hotwordPrivate.startTraining)
|
| + chrome.hotwordPrivate.startTraining();
|
| + };
|
| +
|
| + /**
|
| + * Stops the training process.
|
| + */
|
| + Flow.prototype.stopTraining = function() {
|
| + if (!this.training_)
|
| + return;
|
| +
|
| + this.training_ = false;
|
| + if (chrome.hotwordPrivate.onHotwordTriggered) {
|
| + chrome.hotwordPrivate.onHotwordTriggered.
|
| + removeListener(this.handleHotwordTrigger_);
|
| + }
|
| + if (chrome.hotwordPrivate.stopTraining)
|
| + chrome.hotwordPrivate.stopTraining();
|
| + };
|
| +
|
| + /**
|
| + * Handles the speaker model finalized event.
|
| + */
|
| + Flow.prototype.onSpeakerModelFinalized = function() {
|
| + this.stopTraining();
|
| +
|
| + if (chrome.hotwordPrivate.setAudioLoggingEnabled)
|
| + chrome.hotwordPrivate.setAudioLoggingEnabled(true, function() {});
|
| +
|
| + if (chrome.hotwordPrivate.setHotwordAlwaysOnSearchEnabled) {
|
| + chrome.hotwordPrivate.setHotwordAlwaysOnSearchEnabled(true,
|
| + this.advanceStep.bind(this));
|
| + }
|
| + };
|
| +
|
| // ---- private methods:
|
|
|
| /**
|
| + * Completes the training process.
|
| + * @private
|
| + */
|
| + Flow.prototype.finalizeSpeakerModel_ = function() {
|
| + if (!this.training_)
|
| + return;
|
| +
|
| + if (chrome.hotwordPrivate.finalizeSpeakerModel)
|
| + chrome.hotwordPrivate.finalizeSpeakerModel();
|
| +
|
| + // TODO(kcarattini): Implement a notification that speaker model has been
|
| + // finalized instead of setting a timeout.
|
| + setTimeout(this.onSpeakerModelFinalized.bind(this), 2000);
|
| + };
|
| +
|
| + /**
|
| + * Handles a hotword trigger event and updates the training UI.
|
| + * @private
|
| + */
|
| + Flow.prototype.handleHotwordTrigger_ = function() {
|
| + var curStep =
|
| + $(this.trainingPagePrefix_ + '-training').querySelector('.listening');
|
| + // TODO(kcarattini): Localize this string.
|
| + curStep.querySelector('.text').textContent = 'Recorded';
|
| + curStep.classList.remove('listening');
|
| + curStep.classList.add('recorded');
|
| +
|
| + var steps =
|
| + $(this.trainingPagePrefix_ + '-training').querySelectorAll('.train');
|
| + var index = Array.prototype.indexOf.call(steps, curStep);
|
| + if (steps[index + 1]) {
|
| + steps[index + 1].classList.remove('not-started');
|
| + steps[index + 1].classList.add('listening');
|
| + return;
|
| + }
|
| +
|
| + // Only the last step makes it here.
|
| + var buttonElem = $(this.trainingPagePrefix_ + '-cancel-button');
|
| + // TODO(kcarattini): Localize this string.
|
| + buttonElem.textContent = 'Please wait ...';
|
| + buttonElem.classList.add('grayed-out');
|
| + buttonElem.classList.remove('finish-button');
|
| +
|
| + this.finalizeSpeakerModel_();
|
| + };
|
| +
|
| + /**
|
| * Gets and starts the appropriate flow for the launch mode.
|
| + * @param {chrome.hotwordPrivate.LaunchState} state Launch state of the
|
| + * Hotword Audio Verification App.
|
| * @private
|
| */
|
| Flow.prototype.startFlowForMode_ = function(state) {
|
| + this.launchMode_ = state.launchMode;
|
| assert(state.launchMode >= 0 && state.launchMode < FLOWS.length,
|
| 'Invalid Launch Mode.');
|
| this.currentFlow_ = FLOWS[state.launchMode];
|
| this.advanceStep();
|
| + // If the flow begins with a a training step, then start the training flow.
|
| + if (state.launchMode == LaunchMode.HOTWORD_ONLY ||
|
| + state.launchMode == LaunchMode.SPEECH_TRAINING) {
|
| + this.startTraining();
|
| + }
|
| };
|
|
|
| /**
|
|
|