Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2731)

Unified Diff: chrome/browser/resources/hotword_audio_verification/flow.js

Issue 2939273002: DO NOT SUBMIT: what chrome/browser/resources/ could eventually look like with clang-format (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 9c0c4b016000bd674cc6e4203b8a2cd741e25817..c22211492c4e80efcac9922be8393c0a94d0a446 100644
--- a/chrome/browser/resources/hotword_audio_verification/flow.js
+++ b/chrome/browser/resources/hotword_audio_verification/flow.js
@@ -4,566 +4,563 @@
(function() {
- // Correspond to steps in the hotword opt-in flow.
- /** @const */ var START = 'start-container';
- /** @const */ var AUDIO_HISTORY = 'audio-history-container';
- /** @const */ var SPEECH_TRAINING = 'speech-training-container';
- /** @const */ var FINISH = 'finish-container';
+// Correspond to steps in the hotword opt-in flow.
+/** @const */ var START = 'start-container';
+/** @const */ var AUDIO_HISTORY = 'audio-history-container';
+/** @const */ var SPEECH_TRAINING = 'speech-training-container';
+/** @const */ var FINISH = 'finish-container';
+
+/**
+ * These flows correspond to the three LaunchModes as defined in
+ * chrome/browser/search/hotword_service.h and should be kept in sync
+ * with them.
+ * @const
+ */
+var FLOWS = [
+ [START, SPEECH_TRAINING, FINISH],
+ [START, AUDIO_HISTORY, SPEECH_TRAINING, FINISH], [SPEECH_TRAINING, FINISH]
+];
+
+/**
+ * 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};
+
+/**
+ * The training state.
+ * @enum {string}
+ */
+var TrainingState = {
+ RESET: 'reset',
+ TIMEOUT: 'timeout',
+ ERROR: 'error',
+};
+
+/**
+ * Class to control the page flow of the always-on hotword and
+ * Audio History opt-in process.
+ * @constructor
+ */
+function Flow() {
+ this.currentStepIndex_ = -1;
+ this.currentFlow_ = [];
/**
- * These flows correspond to the three LaunchModes as defined in
- * chrome/browser/search/hotword_service.h and should be kept in sync
- * with them.
- * @const
+ * The mode that this app was launched in.
+ * @private {LaunchMode}
*/
- var FLOWS = [
- [START, SPEECH_TRAINING, FINISH],
- [START, AUDIO_HISTORY, SPEECH_TRAINING, FINISH],
- [SPEECH_TRAINING, FINISH]
- ];
+ this.launchMode_ = LaunchMode.HOTWORD_AND_AUDIO_HISTORY;
/**
- * The launch mode. This enum needs to be kept in sync with that of
- * the same name in hotword_service.h.
- * @enum {number}
+ * Whether this flow is currently in the process of training a voice model.
+ * @private {boolean}
*/
- var LaunchMode = {
- HOTWORD_ONLY: 0,
- HOTWORD_AND_AUDIO_HISTORY: 1,
- RETRAIN: 2
- };
-
- /**
- * The training state.
- * @enum {string}
- */
- var TrainingState = {
- RESET: 'reset',
- TIMEOUT: 'timeout',
- ERROR: 'error',
- };
-
- /**
- * Class to control the page flow of the always-on hotword and
- * Audio History opt-in process.
- * @constructor
- */
- function Flow() {
- this.currentStepIndex_ = -1;
- this.currentFlow_ = [];
-
- /**
- * The mode that this app was launched in.
- * @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;
-
- /**
- * The current training state.
- * @private {?TrainingState}
- */
- this.trainingState_ = null;
-
- /**
- * Whether an expected hotword trigger has been received, indexed by
- * training step.
- * @private {boolean[]}
- */
- this.hotwordTriggerReceived_ = [];
-
- /**
- * Prefix of the element ids for the page that is currently training.
- * @private {string}
- */
- this.trainingPagePrefix_ = 'speech-training';
-
- /**
- * Whether the speaker model for this flow has been finalized.
- * @private {boolean}
- */
- this.speakerModelFinalized_ = false;
-
- /**
- * ID of the currently active timeout.
- * @private {?number}
- */
- this.timeoutId_ = null;
-
- /**
- * Listener for the speakerModelSaved event.
- * @private {Function}
- */
- this.speakerModelFinalizedListener_ =
- this.onSpeakerModelFinalized_.bind(this);
-
- /**
- * Listener for the hotword trigger event.
- * @private {Function}
- */
- this.hotwordTriggerListener_ =
- this.handleHotwordTrigger_.bind(this);
-
- // Listen for the user locking the screen.
- chrome.idle.onStateChanged.addListener(
- this.handleIdleStateChanged_.bind(this));
-
- // Listen for hotword settings changes. This used to detect when the user
- // switches to a different profile.
- if (chrome.hotwordPrivate.onEnabledChanged) {
- chrome.hotwordPrivate.onEnabledChanged.addListener(
- this.handleEnabledChanged_.bind(this));
- }
- }
+ this.training_ = false;
/**
- * Advances the current step. Begins training if the speech-training
- * page has been reached.
+ * The current training state.
+ * @private {?TrainingState}
*/
- Flow.prototype.advanceStep = function() {
- this.currentStepIndex_++;
- if (this.currentStepIndex_ < this.currentFlow_.length) {
- if (this.currentFlow_[this.currentStepIndex_] == SPEECH_TRAINING)
- this.startTraining();
- this.showStep_.apply(this);
- }
- };
+ this.trainingState_ = null;
/**
- * Gets the appropriate flow and displays its first page.
+ * Whether an expected hotword trigger has been received, indexed by
+ * training step.
+ * @private {boolean[]}
*/
- Flow.prototype.startFlow = function() {
- if (chrome.hotwordPrivate && chrome.hotwordPrivate.getLaunchState)
- chrome.hotwordPrivate.getLaunchState(this.startFlowForMode_.bind(this));
- };
+ this.hotwordTriggerReceived_ = [];
/**
- * Starts the training process.
+ * Prefix of the element ids for the page that is currently training.
+ * @private {string}
*/
- Flow.prototype.startTraining = function() {
- // Don't start a training session if one already exists.
- if (this.training_)
- return;
-
- this.training_ = true;
-
- if (chrome.hotwordPrivate.onHotwordTriggered &&
- !chrome.hotwordPrivate.onHotwordTriggered.hasListener(
- this.hotwordTriggerListener_)) {
- chrome.hotwordPrivate.onHotwordTriggered.addListener(
- this.hotwordTriggerListener_);
- }
-
- this.waitForHotwordTrigger_(0);
- if (chrome.hotwordPrivate.startTraining)
- chrome.hotwordPrivate.startTraining();
- };
+ this.trainingPagePrefix_ = 'speech-training';
/**
- * Stops the training process.
+ * Whether the speaker model for this flow has been finalized.
+ * @private {boolean}
*/
- Flow.prototype.stopTraining = function() {
- if (!this.training_)
- return;
-
- this.training_ = false;
- if (chrome.hotwordPrivate.onHotwordTriggered) {
- chrome.hotwordPrivate.onHotwordTriggered.
- removeListener(this.hotwordTriggerListener_);
- }
- if (chrome.hotwordPrivate.stopTraining)
- chrome.hotwordPrivate.stopTraining();
- };
+ this.speakerModelFinalized_ = false;
/**
- * Attempts to enable audio history for the signed-in account.
+ * ID of the currently active timeout.
+ * @private {?number}
*/
- Flow.prototype.enableAudioHistory = function() {
- // Update UI
- $('audio-history-agree').disabled = true;
- $('audio-history-cancel').disabled = true;
-
- $('audio-history-error').hidden = true;
- $('audio-history-wait').hidden = false;
-
- if (chrome.hotwordPrivate.setAudioHistoryEnabled) {
- chrome.hotwordPrivate.setAudioHistoryEnabled(
- true, this.onAudioHistoryRequestCompleted_.bind(this));
- }
- };
-
- // ---- private methods:
+ this.timeoutId_ = null;
/**
- * Shows an error if the audio history setting was not enabled successfully.
- * @private
+ * Listener for the speakerModelSaved event.
+ * @private {Function}
*/
- Flow.prototype.handleAudioHistoryError_ = function() {
- $('audio-history-agree').disabled = false;
- $('audio-history-cancel').disabled = false;
-
- $('audio-history-wait').hidden = true;
- $('audio-history-error').hidden = false;
-
- // Set a timeout before focusing the Enable button so that screenreaders
- // have time to announce the error first.
- this.setTimeout_(function() {
- $('audio-history-agree').focus();
- }.bind(this), 50);
- };
+ this.speakerModelFinalizedListener_ =
+ this.onSpeakerModelFinalized_.bind(this);
/**
- * Callback for when an audio history request completes.
- * @param {chrome.hotwordPrivate.AudioHistoryState} state The audio history
- * request state.
- * @private
+ * Listener for the hotword trigger event.
+ * @private {Function}
*/
- Flow.prototype.onAudioHistoryRequestCompleted_ = function(state) {
- if (!state.success || !state.enabled) {
- this.handleAudioHistoryError_();
- return;
- }
+ this.hotwordTriggerListener_ = this.handleHotwordTrigger_.bind(this);
- this.advanceStep();
- };
-
- /**
- * Shows an error if the speaker model has not been finalized.
- * @private
- */
- Flow.prototype.handleSpeakerModelFinalizedError_ = function() {
- if (!this.training_)
- return;
+ // Listen for the user locking the screen.
+ chrome.idle.onStateChanged.addListener(
+ this.handleIdleStateChanged_.bind(this));
- if (this.speakerModelFinalized_)
- return;
-
- this.updateTrainingState_(TrainingState.ERROR);
- this.stopTraining();
- };
+ // Listen for hotword settings changes. This used to detect when the user
+ // switches to a different profile.
+ if (chrome.hotwordPrivate.onEnabledChanged) {
+ chrome.hotwordPrivate.onEnabledChanged.addListener(
+ this.handleEnabledChanged_.bind(this));
+ }
+}
+
+/**
+ * Advances the current step. Begins training if the speech-training
+ * page has been reached.
+ */
+Flow.prototype.advanceStep = function() {
+ this.currentStepIndex_++;
+ if (this.currentStepIndex_ < this.currentFlow_.length) {
+ if (this.currentFlow_[this.currentStepIndex_] == SPEECH_TRAINING)
+ this.startTraining();
+ this.showStep_.apply(this);
+ }
+};
+
+/**
+ * Gets the appropriate flow and displays its first page.
+ */
+Flow.prototype.startFlow = function() {
+ if (chrome.hotwordPrivate && chrome.hotwordPrivate.getLaunchState)
+ 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 (chrome.hotwordPrivate.onHotwordTriggered &&
+ !chrome.hotwordPrivate.onHotwordTriggered.hasListener(
+ this.hotwordTriggerListener_)) {
+ chrome.hotwordPrivate.onHotwordTriggered.addListener(
+ this.hotwordTriggerListener_);
+ }
- /**
- * Handles the speaker model finalized event.
- * @private
- */
- Flow.prototype.onSpeakerModelFinalized_ = function() {
- this.speakerModelFinalized_ = true;
- if (chrome.hotwordPrivate.onSpeakerModelSaved) {
- chrome.hotwordPrivate.onSpeakerModelSaved.removeListener(
- this.speakerModelFinalizedListener_);
- }
- this.stopTraining();
- this.setTimeout_(this.finishFlow_.bind(this), 2000);
- };
+ this.waitForHotwordTrigger_(0);
+ 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.hotwordTriggerListener_);
+ }
+ if (chrome.hotwordPrivate.stopTraining)
+ chrome.hotwordPrivate.stopTraining();
+};
+
+/**
+ * Attempts to enable audio history for the signed-in account.
+ */
+Flow.prototype.enableAudioHistory = function() {
+ // Update UI
+ $('audio-history-agree').disabled = true;
+ $('audio-history-cancel').disabled = true;
+
+ $('audio-history-error').hidden = true;
+ $('audio-history-wait').hidden = false;
+
+ if (chrome.hotwordPrivate.setAudioHistoryEnabled) {
+ chrome.hotwordPrivate.setAudioHistoryEnabled(
+ true, this.onAudioHistoryRequestCompleted_.bind(this));
+ }
+};
+
+// ---- private methods:
+
+/**
+ * Shows an error if the audio history setting was not enabled successfully.
+ * @private
+ */
+Flow.prototype.handleAudioHistoryError_ = function() {
+ $('audio-history-agree').disabled = false;
+ $('audio-history-cancel').disabled = false;
+
+ $('audio-history-wait').hidden = true;
+ $('audio-history-error').hidden = false;
+
+ // Set a timeout before focusing the Enable button so that screenreaders
+ // have time to announce the error first.
+ this.setTimeout_(function() {
+ $('audio-history-agree').focus();
+ }.bind(this), 50);
+};
+
+/**
+ * Callback for when an audio history request completes.
+ * @param {chrome.hotwordPrivate.AudioHistoryState} state The audio history
+ * request state.
+ * @private
+ */
+Flow.prototype.onAudioHistoryRequestCompleted_ = function(state) {
+ if (!state.success || !state.enabled) {
+ this.handleAudioHistoryError_();
+ return;
+ }
- /**
- * Completes the training process.
- * @private
- */
- Flow.prototype.finishFlow_ = function() {
- if (chrome.hotwordPrivate.setHotwordAlwaysOnSearchEnabled) {
- chrome.hotwordPrivate.setHotwordAlwaysOnSearchEnabled(true,
- this.advanceStep.bind(this));
- }
- };
+ this.advanceStep();
+};
+
+/**
+ * Shows an error if the speaker model has not been finalized.
+ * @private
+ */
+Flow.prototype.handleSpeakerModelFinalizedError_ = function() {
+ if (!this.training_)
+ return;
+
+ if (this.speakerModelFinalized_)
+ return;
+
+ this.updateTrainingState_(TrainingState.ERROR);
+ this.stopTraining();
+};
+
+/**
+ * Handles the speaker model finalized event.
+ * @private
+ */
+Flow.prototype.onSpeakerModelFinalized_ = function() {
+ this.speakerModelFinalized_ = true;
+ if (chrome.hotwordPrivate.onSpeakerModelSaved) {
+ chrome.hotwordPrivate.onSpeakerModelSaved.removeListener(
+ this.speakerModelFinalizedListener_);
+ }
+ this.stopTraining();
+ this.setTimeout_(this.finishFlow_.bind(this), 2000);
+};
+
+/**
+ * Completes the training process.
+ * @private
+ */
+Flow.prototype.finishFlow_ = function() {
+ if (chrome.hotwordPrivate.setHotwordAlwaysOnSearchEnabled) {
+ chrome.hotwordPrivate.setHotwordAlwaysOnSearchEnabled(
+ true, this.advanceStep.bind(this));
+ }
+};
- /**
- * Handles a user clicking on the retry button.
- */
- Flow.prototype.handleRetry = function() {
- if (!(this.trainingState_ == TrainingState.TIMEOUT ||
+/**
+ * Handles a user clicking on the retry button.
+ */
+Flow.prototype.handleRetry = function() {
+ if (!(this.trainingState_ == TrainingState.TIMEOUT ||
this.trainingState_ == TrainingState.ERROR))
- return;
-
- this.startTraining();
- this.updateTrainingState_(TrainingState.RESET);
- };
-
- // ---- private methods:
-
- /**
- * Completes the training process.
- * @private
- */
- Flow.prototype.finalizeSpeakerModel_ = function() {
- if (!this.training_)
- return;
-
- // Listen for the success event from the NaCl module.
- if (chrome.hotwordPrivate.onSpeakerModelSaved &&
- !chrome.hotwordPrivate.onSpeakerModelSaved.hasListener(
- this.speakerModelFinalizedListener_)) {
- chrome.hotwordPrivate.onSpeakerModelSaved.addListener(
- this.speakerModelFinalizedListener_);
- }
-
- this.speakerModelFinalized_ = false;
- this.setTimeout_(this.handleSpeakerModelFinalizedError_.bind(this), 30000);
- if (chrome.hotwordPrivate.finalizeSpeakerModel)
- chrome.hotwordPrivate.finalizeSpeakerModel();
- };
-
- /**
- * Returns the current training step.
- * @param {string} curStepClassName The name of the class of the current
- * training step.
- * @return {Object} The current training step, its index, and an array of
- * all training steps. Any of these can be undefined.
- * @private
- */
- Flow.prototype.getCurrentTrainingStep_ = function(curStepClassName) {
- var steps =
- $(this.trainingPagePrefix_ + '-training').querySelectorAll('.train');
- var curStep =
- $(this.trainingPagePrefix_ + '-training').querySelector('.listening');
-
- return {current: curStep,
- index: Array.prototype.indexOf.call(steps, curStep),
- steps: steps};
- };
-
- /**
- * Updates the training state.
- * @param {TrainingState} state The training state.
- * @private
- */
- Flow.prototype.updateTrainingState_ = function(state) {
- this.trainingState_ = state;
- this.updateErrorUI_();
- };
-
- /**
- * Waits two minutes and then checks for a training error.
- * @param {number} index The index of the training step.
- * @private
- */
- Flow.prototype.waitForHotwordTrigger_ = function(index) {
- if (!this.training_)
- return;
-
- this.hotwordTriggerReceived_[index] = false;
- this.setTimeout_(this.handleTrainingTimeout_.bind(this, index), 120000);
- };
-
- /**
- * Checks for and handles a training error.
- * @param {number} index The index of the training step.
- * @private
- */
- Flow.prototype.handleTrainingTimeout_ = function(index) {
- if (this.hotwordTriggerReceived_[index])
- return;
-
- this.timeoutTraining_();
- };
-
- /**
- * Times out training and updates the UI to show a "retry" message, if
- * currently training.
- * @private
- */
- Flow.prototype.timeoutTraining_ = function() {
- if (!this.training_)
- return;
-
- this.clearTimeout_();
- this.updateTrainingState_(TrainingState.TIMEOUT);
- this.stopTraining();
- };
+ return;
+
+ this.startTraining();
+ this.updateTrainingState_(TrainingState.RESET);
+};
+
+// ---- private methods:
+
+/**
+ * Completes the training process.
+ * @private
+ */
+Flow.prototype.finalizeSpeakerModel_ = function() {
+ if (!this.training_)
+ return;
+
+ // Listen for the success event from the NaCl module.
+ if (chrome.hotwordPrivate.onSpeakerModelSaved &&
+ !chrome.hotwordPrivate.onSpeakerModelSaved.hasListener(
+ this.speakerModelFinalizedListener_)) {
+ chrome.hotwordPrivate.onSpeakerModelSaved.addListener(
+ this.speakerModelFinalizedListener_);
+ }
- /**
- * Sets a timeout. If any timeout is active, clear it.
- * @param {Function} func The function to invoke when the timeout occurs.
- * @param {number} delay Timeout delay in milliseconds.
- * @private
- */
- Flow.prototype.setTimeout_ = function(func, delay) {
- this.clearTimeout_();
- this.timeoutId_ = setTimeout(function() {
- this.timeoutId_ = null;
- func();
- }, delay);
+ this.speakerModelFinalized_ = false;
+ this.setTimeout_(this.handleSpeakerModelFinalizedError_.bind(this), 30000);
+ if (chrome.hotwordPrivate.finalizeSpeakerModel)
+ chrome.hotwordPrivate.finalizeSpeakerModel();
+};
+
+/**
+ * Returns the current training step.
+ * @param {string} curStepClassName The name of the class of the current
+ * training step.
+ * @return {Object} The current training step, its index, and an array of
+ * all training steps. Any of these can be undefined.
+ * @private
+ */
+Flow.prototype.getCurrentTrainingStep_ = function(curStepClassName) {
+ var steps =
+ $(this.trainingPagePrefix_ + '-training').querySelectorAll('.train');
+ var curStep =
+ $(this.trainingPagePrefix_ + '-training').querySelector('.listening');
+
+ return {
+ current: curStep,
+ index: Array.prototype.indexOf.call(steps, curStep),
+ steps: steps
};
-
- /**
- * Clears any currently active timeout.
- * @private
- */
- Flow.prototype.clearTimeout_ = function() {
- if (this.timeoutId_ != null) {
- clearTimeout(this.timeoutId_);
- this.timeoutId_ = null;
- }
- };
-
- /**
- * Updates the training error UI.
- * @private
- */
- Flow.prototype.updateErrorUI_ = function() {
- if (!this.training_)
- return;
-
- var trainingSteps = this.getCurrentTrainingStep_('listening');
- var steps = trainingSteps.steps;
-
- $(this.trainingPagePrefix_ + '-toast').hidden =
- this.trainingState_ != TrainingState.TIMEOUT;
- if (this.trainingState_ == TrainingState.RESET) {
- // We reset the training to begin at the first step.
- // The first step is reset to 'listening', while the rest
- // are reset to 'not-started'.
- var prompt = loadTimeData.getString('trainingFirstPrompt');
- for (var i = 0; i < steps.length; ++i) {
- steps[i].classList.remove('recorded');
- if (i == 0) {
- steps[i].classList.remove('not-started');
- steps[i].classList.add('listening');
- } else {
- steps[i].classList.add('not-started');
- if (i == steps.length - 1)
- prompt = loadTimeData.getString('trainingLastPrompt');
- else
- prompt = loadTimeData.getString('trainingMiddlePrompt');
- }
- steps[i].querySelector('.text').textContent = prompt;
- }
-
- // Reset the buttonbar.
- $(this.trainingPagePrefix_ + '-processing').hidden = true;
- $(this.trainingPagePrefix_ + '-wait').hidden = false;
- $(this.trainingPagePrefix_ + '-error').hidden = true;
- $(this.trainingPagePrefix_ + '-retry').hidden = true;
- } else if (this.trainingState_ == TrainingState.TIMEOUT) {
- var curStep = trainingSteps.current;
- if (curStep) {
- curStep.classList.remove('listening');
- curStep.classList.add('not-started');
+};
+
+/**
+ * Updates the training state.
+ * @param {TrainingState} state The training state.
+ * @private
+ */
+Flow.prototype.updateTrainingState_ = function(state) {
+ this.trainingState_ = state;
+ this.updateErrorUI_();
+};
+
+/**
+ * Waits two minutes and then checks for a training error.
+ * @param {number} index The index of the training step.
+ * @private
+ */
+Flow.prototype.waitForHotwordTrigger_ = function(index) {
+ if (!this.training_)
+ return;
+
+ this.hotwordTriggerReceived_[index] = false;
+ this.setTimeout_(this.handleTrainingTimeout_.bind(this, index), 120000);
+};
+
+/**
+ * Checks for and handles a training error.
+ * @param {number} index The index of the training step.
+ * @private
+ */
+Flow.prototype.handleTrainingTimeout_ = function(index) {
+ if (this.hotwordTriggerReceived_[index])
+ return;
+
+ this.timeoutTraining_();
+};
+
+/**
+ * Times out training and updates the UI to show a "retry" message, if
+ * currently training.
+ * @private
+ */
+Flow.prototype.timeoutTraining_ = function() {
+ if (!this.training_)
+ return;
+
+ this.clearTimeout_();
+ this.updateTrainingState_(TrainingState.TIMEOUT);
+ this.stopTraining();
+};
+
+/**
+ * Sets a timeout. If any timeout is active, clear it.
+ * @param {Function} func The function to invoke when the timeout occurs.
+ * @param {number} delay Timeout delay in milliseconds.
+ * @private
+ */
+Flow.prototype.setTimeout_ = function(func, delay) {
+ this.clearTimeout_();
+ this.timeoutId_ = setTimeout(function() {
+ this.timeoutId_ = null;
+ func();
+ }, delay);
+};
+
+/**
+ * Clears any currently active timeout.
+ * @private
+ */
+Flow.prototype.clearTimeout_ = function() {
+ if (this.timeoutId_ != null) {
+ clearTimeout(this.timeoutId_);
+ this.timeoutId_ = null;
+ }
+};
+
+/**
+ * Updates the training error UI.
+ * @private
+ */
+Flow.prototype.updateErrorUI_ = function() {
+ if (!this.training_)
+ return;
+
+ var trainingSteps = this.getCurrentTrainingStep_('listening');
+ var steps = trainingSteps.steps;
+
+ $(this.trainingPagePrefix_ + '-toast').hidden =
+ this.trainingState_ != TrainingState.TIMEOUT;
+ if (this.trainingState_ == TrainingState.RESET) {
+ // We reset the training to begin at the first step.
+ // The first step is reset to 'listening', while the rest
+ // are reset to 'not-started'.
+ var prompt = loadTimeData.getString('trainingFirstPrompt');
+ for (var i = 0; i < steps.length; ++i) {
+ steps[i].classList.remove('recorded');
+ if (i == 0) {
+ steps[i].classList.remove('not-started');
+ steps[i].classList.add('listening');
+ } else {
+ steps[i].classList.add('not-started');
+ if (i == steps.length - 1)
+ prompt = loadTimeData.getString('trainingLastPrompt');
+ else
+ prompt = loadTimeData.getString('trainingMiddlePrompt');
}
-
- // Set a timeout before focusing the Retry button so that screenreaders
- // have time to announce the timeout first.
- this.setTimeout_(function() {
- $(this.trainingPagePrefix_ + '-toast').children[1].focus();
- }.bind(this), 50);
- } else if (this.trainingState_ == TrainingState.ERROR) {
- // Update the buttonbar.
- $(this.trainingPagePrefix_ + '-wait').hidden = true;
- $(this.trainingPagePrefix_ + '-error').hidden = false;
- $(this.trainingPagePrefix_ + '-retry').hidden = false;
- $(this.trainingPagePrefix_ + '-processing').hidden = false;
-
- // Set a timeout before focusing the Retry button so that screenreaders
- // have time to announce the error first.
- this.setTimeout_(function() {
- $(this.trainingPagePrefix_ + '-retry').children[0].focus();
- }.bind(this), 50);
+ steps[i].querySelector('.text').textContent = prompt;
}
- };
-
- /**
- * Handles a hotword trigger event and updates the training UI.
- * @private
- */
- Flow.prototype.handleHotwordTrigger_ = function() {
- var trainingSteps = this.getCurrentTrainingStep_('listening');
-
- if (!trainingSteps.current)
- return;
- var index = trainingSteps.index;
- this.hotwordTriggerReceived_[index] = true;
-
- trainingSteps.current.querySelector('.text').textContent =
- loadTimeData.getString('trainingRecorded');
- trainingSteps.current.classList.remove('listening');
- trainingSteps.current.classList.add('recorded');
-
- if (trainingSteps.steps[index + 1]) {
- trainingSteps.steps[index + 1].classList.remove('not-started');
- trainingSteps.steps[index + 1].classList.add('listening');
- this.waitForHotwordTrigger_(index + 1);
- return;
+ // Reset the buttonbar.
+ $(this.trainingPagePrefix_ + '-processing').hidden = true;
+ $(this.trainingPagePrefix_ + '-wait').hidden = false;
+ $(this.trainingPagePrefix_ + '-error').hidden = true;
+ $(this.trainingPagePrefix_ + '-retry').hidden = true;
+ } else if (this.trainingState_ == TrainingState.TIMEOUT) {
+ var curStep = trainingSteps.current;
+ if (curStep) {
+ curStep.classList.remove('listening');
+ curStep.classList.add('not-started');
}
- // Only the last step makes it here.
- var buttonElem = $(this.trainingPagePrefix_ + '-processing').hidden = false;
- this.finalizeSpeakerModel_();
- };
-
- /**
- * Handles a chrome.idle.onStateChanged event and times out the training if
- * the state is "locked".
- * @param {!string} state State, one of "active", "idle", or "locked".
- * @private
- */
- Flow.prototype.handleIdleStateChanged_ = function(state) {
- if (state == 'locked')
- this.timeoutTraining_();
- };
+ // Set a timeout before focusing the Retry button so that screenreaders
+ // have time to announce the timeout first.
+ this.setTimeout_(function() {
+ $(this.trainingPagePrefix_ + '-toast').children[1].focus();
+ }.bind(this), 50);
+ } else if (this.trainingState_ == TrainingState.ERROR) {
+ // Update the buttonbar.
+ $(this.trainingPagePrefix_ + '-wait').hidden = true;
+ $(this.trainingPagePrefix_ + '-error').hidden = false;
+ $(this.trainingPagePrefix_ + '-retry').hidden = false;
+ $(this.trainingPagePrefix_ + '-processing').hidden = false;
+
+ // Set a timeout before focusing the Retry button so that screenreaders
+ // have time to announce the error first.
+ this.setTimeout_(function() {
+ $(this.trainingPagePrefix_ + '-retry').children[0].focus();
+ }.bind(this), 50);
+ }
+};
+
+/**
+ * Handles a hotword trigger event and updates the training UI.
+ * @private
+ */
+Flow.prototype.handleHotwordTrigger_ = function() {
+ var trainingSteps = this.getCurrentTrainingStep_('listening');
+
+ if (!trainingSteps.current)
+ return;
+
+ var index = trainingSteps.index;
+ this.hotwordTriggerReceived_[index] = true;
+
+ trainingSteps.current.querySelector('.text').textContent =
+ loadTimeData.getString('trainingRecorded');
+ trainingSteps.current.classList.remove('listening');
+ trainingSteps.current.classList.add('recorded');
+
+ if (trainingSteps.steps[index + 1]) {
+ trainingSteps.steps[index + 1].classList.remove('not-started');
+ trainingSteps.steps[index + 1].classList.add('listening');
+ this.waitForHotwordTrigger_(index + 1);
+ return;
+ }
- /**
- * Handles a chrome.hotwordPrivate.onEnabledChanged event and times out
- * training if the user is no longer the active user (user switches profiles).
- * @private
- */
- Flow.prototype.handleEnabledChanged_ = function() {
- if (chrome.hotwordPrivate.getStatus) {
- chrome.hotwordPrivate.getStatus(function(status) {
- if (status.userIsActive)
- return;
-
- this.timeoutTraining_();
- }.bind(this));
- }
- };
+ // Only the last step makes it here.
+ var buttonElem = $(this.trainingPagePrefix_ + '-processing').hidden = false;
+ this.finalizeSpeakerModel_();
+};
+
+/**
+ * Handles a chrome.idle.onStateChanged event and times out the training if
+ * the state is "locked".
+ * @param {!string} state State, one of "active", "idle", or "locked".
+ * @private
+ */
+Flow.prototype.handleIdleStateChanged_ = function(state) {
+ if (state == 'locked')
+ this.timeoutTraining_();
+};
+
+/**
+ * Handles a chrome.hotwordPrivate.onEnabledChanged event and times out
+ * training if the user is no longer the active user (user switches profiles).
+ * @private
+ */
+Flow.prototype.handleEnabledChanged_ = function() {
+ if (chrome.hotwordPrivate.getStatus) {
+ chrome.hotwordPrivate.getStatus(function(status) {
+ if (status.userIsActive)
+ return;
- /**
- * 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];
- if (state.launchMode == LaunchMode.HOTWORD_ONLY) {
- $('intro-description-audio-history-enabled').hidden = false;
- } else if (state.launchMode == LaunchMode.HOTWORD_AND_AUDIO_HISTORY) {
- $('intro-description').hidden = false;
- }
+ this.timeoutTraining_();
+ }.bind(this));
+ }
+};
+
+/**
+ * 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];
+ if (state.launchMode == LaunchMode.HOTWORD_ONLY) {
+ $('intro-description-audio-history-enabled').hidden = false;
+ } else if (state.launchMode == LaunchMode.HOTWORD_AND_AUDIO_HISTORY) {
+ $('intro-description').hidden = false;
+ }
- this.advanceStep();
- };
+ this.advanceStep();
+};
- /**
- * Displays the current step. If the current step is not the first step,
- * also hides the previous step. Focuses the current step's first button.
- * @private
- */
- Flow.prototype.showStep_ = function() {
- var currentStepId = this.currentFlow_[this.currentStepIndex_];
- var currentStep = document.getElementById(currentStepId);
- currentStep.hidden = false;
+/**
+ * Displays the current step. If the current step is not the first step,
+ * also hides the previous step. Focuses the current step's first button.
+ * @private
+ */
+Flow.prototype.showStep_ = function() {
+ var currentStepId = this.currentFlow_[this.currentStepIndex_];
+ var currentStep = document.getElementById(currentStepId);
+ currentStep.hidden = false;
- cr.ui.setInitialFocus(currentStep);
+ cr.ui.setInitialFocus(currentStep);
- var previousStep = null;
- if (this.currentStepIndex_ > 0)
- previousStep = this.currentFlow_[this.currentStepIndex_ - 1];
+ var previousStep = null;
+ if (this.currentStepIndex_ > 0)
+ previousStep = this.currentFlow_[this.currentStepIndex_ - 1];
- if (previousStep)
- document.getElementById(previousStep).hidden = true;
+ if (previousStep)
+ document.getElementById(previousStep).hidden = true;
- chrome.app.window.current().show();
- };
+ chrome.app.window.current().show();
+};
- window.Flow = Flow;
+window.Flow = Flow;
})();

Powered by Google App Engine
This is Rietveld 408576698