Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / hotword_audio_verification / flow.js
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 (function() {
6
7   // Correspond to steps in the hotword opt-in flow.
8   /** @const */ var HOTWORD_AUDIO_HISTORY = 'hotword-audio-history-container';
9   /** @const */ var HOTWORD_ONLY_START = 'hotword-only-container';
10   /** @const */ var SPEECH_TRAINING = 'speech-training-container';
11   /** @const */ var FINISHED = 'finished-container';
12
13   /**
14    * These flows correspond to the three LaunchModes as defined in
15    * chrome/browser/search/hotword_service.h and should be kept in sync
16    * with them.
17    * @const
18    */
19   var FLOWS = [
20     [HOTWORD_ONLY_START, FINISHED],
21     [HOTWORD_AUDIO_HISTORY, SPEECH_TRAINING, FINISHED],
22     [SPEECH_TRAINING, FINISHED]
23   ];
24
25   /**
26    * The launch mode. This enum needs to be kept in sync with that of
27    * the same name in hotword_service.h.
28    * @enum {number}
29    */
30   var LaunchMode = {
31     HOTWORD_ONLY: 0,
32     HOTWORD_AND_AUDIO_HISTORY: 1,
33     RETRAIN: 2
34   };
35
36   /**
37    * Class to control the page flow of the always-on hotword and
38    * Audio History opt-in process.
39    * @constructor
40    */
41   function Flow() {
42     this.currentStepIndex_ = -1;
43     this.currentFlow_ = [];
44
45     /**
46      * Whether this flow is currently in the process of training a voice model.
47      * @private {LaunchMode}
48      */
49     this.launchMode_ = LaunchMode.HOTWORD_AND_AUDIO_HISTORY;
50
51     /**
52      * Whether this flow is currently in the process of training a voice model.
53      * @private {boolean}
54      */
55     this.training_ = false;
56
57     /**
58      * Prefix of the element ids for the page that is currently training.
59      * @private {string}
60      */
61     this.trainingPagePrefix_ = '';
62   }
63
64   /**
65    * Advances the current step.
66    */
67   Flow.prototype.advanceStep = function() {
68     this.currentStepIndex_++;
69     if (this.currentStepIndex_ < this.currentFlow_.length)
70       this.showStep_.apply(this);
71   };
72
73   /**
74    * Gets the appropriate flow and displays its first page.
75    */
76   Flow.prototype.startFlow = function() {
77     if (chrome.hotwordPrivate && chrome.hotwordPrivate.getLaunchState)
78       chrome.hotwordPrivate.getLaunchState(this.startFlowForMode_.bind(this));
79   };
80
81   /**
82    * Starts the training process.
83    */
84   Flow.prototype.startTraining = function() {
85     // Don't start a training session if one already exists.
86     if (this.training_)
87       return;
88
89     this.training_ = true;
90     if (this.launchMode_ == LaunchMode.HOTWORD_ONLY) {
91       this.trainingPagePrefix_ = 'hotword-only';
92     } else if (this.launchMode_ == LaunchMode.HOTWORD_AND_AUDIO_HISTORY ||
93                this.launchMode_ == LaunchMode.RETRAIN) {
94       this.trainingPagePrefix_ = 'speech-training';
95     }
96
97     if (chrome.hotwordPrivate.onHotwordTriggered) {
98       chrome.hotwordPrivate.onHotwordTriggered.addListener(
99           this.handleHotwordTrigger_.bind(this));
100     }
101     if (chrome.hotwordPrivate.startTraining)
102       chrome.hotwordPrivate.startTraining();
103   };
104
105   /**
106    * Stops the training process.
107    */
108   Flow.prototype.stopTraining = function() {
109     if (!this.training_)
110       return;
111
112     this.training_ = false;
113     if (chrome.hotwordPrivate.onHotwordTriggered) {
114       chrome.hotwordPrivate.onHotwordTriggered.
115           removeListener(this.handleHotwordTrigger_);
116     }
117     if (chrome.hotwordPrivate.stopTraining)
118       chrome.hotwordPrivate.stopTraining();
119   };
120
121   /**
122    * Handles the speaker model finalized event.
123    */
124   Flow.prototype.onSpeakerModelFinalized = function() {
125     this.stopTraining();
126
127     if (chrome.hotwordPrivate.setAudioLoggingEnabled)
128       chrome.hotwordPrivate.setAudioLoggingEnabled(true, function() {});
129
130     if (chrome.hotwordPrivate.setHotwordAlwaysOnSearchEnabled) {
131       chrome.hotwordPrivate.setHotwordAlwaysOnSearchEnabled(true,
132           this.advanceStep.bind(this));
133     }
134   };
135
136   // ---- private methods:
137
138   /**
139    * Completes the training process.
140    * @private
141    */
142   Flow.prototype.finalizeSpeakerModel_ = function() {
143     if (!this.training_)
144       return;
145
146     if (chrome.hotwordPrivate.finalizeSpeakerModel)
147       chrome.hotwordPrivate.finalizeSpeakerModel();
148
149     // TODO(kcarattini): Implement a notification that speaker model has been
150     // finalized instead of setting a timeout.
151     setTimeout(this.onSpeakerModelFinalized.bind(this), 2000);
152   };
153
154   /**
155    * Handles a hotword trigger event and updates the training UI.
156    * @private
157    */
158   Flow.prototype.handleHotwordTrigger_ = function() {
159     var curStep =
160         $(this.trainingPagePrefix_ + '-training').querySelector('.listening');
161     // TODO(kcarattini): Localize this string.
162     curStep.querySelector('.text').textContent = 'Recorded';
163     curStep.classList.remove('listening');
164     curStep.classList.add('recorded');
165
166     var steps =
167         $(this.trainingPagePrefix_ + '-training').querySelectorAll('.train');
168     var index = Array.prototype.indexOf.call(steps, curStep);
169     if (steps[index + 1]) {
170       steps[index + 1].classList.remove('not-started');
171       steps[index + 1].classList.add('listening');
172       return;
173     }
174
175     // Only the last step makes it here.
176     var buttonElem = $(this.trainingPagePrefix_ + '-cancel-button');
177     // TODO(kcarattini): Localize this string.
178     buttonElem.textContent = 'Please wait ...';
179     buttonElem.classList.add('grayed-out');
180     buttonElem.classList.remove('finish-button');
181
182     this.finalizeSpeakerModel_();
183   };
184
185   /**
186    * Gets and starts the appropriate flow for the launch mode.
187    * @param {chrome.hotwordPrivate.LaunchState} state Launch state of the
188    *     Hotword Audio Verification App.
189    * @private
190    */
191   Flow.prototype.startFlowForMode_ = function(state) {
192     this.launchMode_ = state.launchMode;
193     assert(state.launchMode >= 0 && state.launchMode < FLOWS.length,
194            'Invalid Launch Mode.');
195     this.currentFlow_ = FLOWS[state.launchMode];
196     this.advanceStep();
197     // If the flow begins with a a training step, then start the training flow.
198     if (state.launchMode == LaunchMode.HOTWORD_ONLY ||
199         state.launchMode == LaunchMode.RETRAIN) {
200       this.startTraining();
201     }
202   };
203
204   /**
205    * Displays the current step. If the current step is not the first step,
206    * also hides the previous step.
207    * @private
208    */
209   Flow.prototype.showStep_ = function() {
210     var currentStep = this.currentFlow_[this.currentStepIndex_];
211     document.getElementById(currentStep).hidden = false;
212
213     var previousStep = null;
214     if (this.currentStepIndex_ > 0)
215       previousStep = this.currentFlow_[this.currentStepIndex_ - 1];
216
217     if (previousStep)
218       document.getElementById(previousStep).hidden = true;
219
220     chrome.app.window.current().show();
221   };
222
223   window.Flow = Flow;
224 })();