Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 cr.define('hotword', function() { | 5 cr.define('hotword', function() { |
| 6 'use strict'; | 6 'use strict'; |
| 7 | 7 |
| 8 /** | 8 /** |
| 9 * Class to manage hotwording state. Starts/stops the hotword detector based | 9 * Class to manage hotwording state. Starts/stops the hotword detector based |
| 10 * on user settings, session requests, and any other factors that play into | 10 * on user settings, session requests, and any other factors that play into |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 * @private {?chrome.hotwordPrivate.StatusDetails} | 24 * @private {?chrome.hotwordPrivate.StatusDetails} |
| 25 */ | 25 */ |
| 26 this.hotwordStatus_ = null; | 26 this.hotwordStatus_ = null; |
| 27 | 27 |
| 28 /** | 28 /** |
| 29 * NaCl plugin manager. | 29 * NaCl plugin manager. |
| 30 * @private {?hotword.NaClManager} | 30 * @private {?hotword.NaClManager} |
| 31 */ | 31 */ |
| 32 this.pluginManager_ = null; | 32 this.pluginManager_ = null; |
| 33 | 33 |
| 34 /** | |
| 35 * Source of the current hotword session. | |
| 36 * @private {?hotword.constants.SessionSource} | |
| 37 */ | |
| 38 this.sessionSource_ = null; | |
| 39 | |
| 40 /** | |
| 41 * Callback to run when the hotword detector has successfully started. | |
| 42 * @private {!function()} | |
| 43 */ | |
| 44 this.sessionStartedCb_ = null; | |
| 45 | |
| 34 // Get the initial status. | 46 // Get the initial status. |
| 35 chrome.hotwordPrivate.getStatus(this.handleStatus_.bind(this)); | 47 chrome.hotwordPrivate.getStatus(this.handleStatus_.bind(this)); |
| 36 } | 48 } |
| 37 | 49 |
| 38 /** | 50 /** |
| 39 * @enum {number} | 51 * @enum {number} |
| 40 * @private | 52 * @private |
| 41 */ | 53 */ |
| 42 StateManager.State_ = { | 54 StateManager.State_ = { |
| 43 STOPPED: 0, | 55 STOPPED: 0, |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 66 this.hotwordStatus_ = status; | 78 this.hotwordStatus_ = status; |
| 67 this.updateStateFromStatus_(); | 79 this.updateStateFromStatus_(); |
| 68 }, | 80 }, |
| 69 | 81 |
| 70 /** | 82 /** |
| 71 * Updates state based on the current status. | 83 * Updates state based on the current status. |
| 72 * @private | 84 * @private |
| 73 */ | 85 */ |
| 74 updateStateFromStatus_: function() { | 86 updateStateFromStatus_: function() { |
| 75 if (this.hotwordStatus_.enabled) { | 87 if (this.hotwordStatus_.enabled) { |
| 76 // Hotwording is enabled. | 88 // Start the detector if there's a session, and shut it down if there |
| 77 // TODO(amistry): Have a separate alwaysOnEnabled flag. For now, treat | 89 // isn't. |
| 78 // "enabled" as "always on enabled". | 90 // TODO(amistry): Support stacking sessions. This can happen when the |
| 79 this.startDetector_(); | 91 // user opens google.com or the NTP, then opens the launcher. Opening |
| 92 // google.com will create one session, and opening the launcher will | |
| 93 // create the second. Closing the launcher should re-activate the | |
| 94 // google.com session. | |
| 95 // NOTE(amistry): With always-on, we want a different behaviour with | |
| 96 // sessions since the detector should always be running. The exception | |
| 97 // being when the user triggers by saying 'Ok Google'. In that case, the | |
| 98 // detector stops, so starting/stopping the launcher session should | |
| 99 // restart the detector. | |
| 100 if (this.sessionSource_) | |
| 101 this.startDetector_(); | |
| 102 else | |
| 103 this.shutdownDetector_(); | |
| 80 } else { | 104 } else { |
| 81 // Not enabled. Shut down if running. | 105 // Not enabled. Shut down if running. |
| 82 this.shutdownDetector_(); | 106 this.shutdownDetector_(); |
| 83 } | 107 } |
| 84 }, | 108 }, |
| 85 | 109 |
| 86 /** | 110 /** |
| 87 * Starts the hotword detector. | 111 * Starts the hotword detector. |
| 88 * @private | 112 * @private |
| 89 */ | 113 */ |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 119 this.shutdownPluginManager_(); | 143 this.shutdownPluginManager_(); |
| 120 } | 144 } |
| 121 }.bind(this), | 145 }.bind(this), |
| 122 function(error) { | 146 function(error) { |
| 123 this.state_ = State_.ERROR; | 147 this.state_ = State_.ERROR; |
| 124 this.pluginManager_ = null; | 148 this.pluginManager_ = null; |
| 125 }.bind(this)); | 149 }.bind(this)); |
| 126 }.bind(this)); | 150 }.bind(this)); |
| 127 } else if (this.state_ != State_.STARTING) { | 151 } else if (this.state_ != State_.STARTING) { |
| 128 // Don't try to start a starting detector. | 152 // Don't try to start a starting detector. |
| 129 this.state_ = State_.RUNNING; | 153 this.startRecognizer_(); |
| 130 this.pluginManager_.startRecognizer(); | |
| 131 } | 154 } |
| 132 }, | 155 }, |
| 133 | 156 |
| 134 /** | 157 /** |
| 158 * Start the recognizer plugin. Assumes the plugin has been loaded and is | |
| 159 * ready to start. | |
| 160 * @private | |
| 161 */ | |
| 162 startRecognizer_: function() { | |
| 163 assert(this.pluginManager_); | |
| 164 if (this.state_ != State_.RUNNING) { | |
| 165 this.state_ = State_.RUNNING; | |
| 166 this.pluginManager_.startRecognizer(); | |
| 167 } | |
| 168 if (this.sessionStartedCb_) { | |
| 169 this.sessionStartedCb_(); | |
| 170 this.sessionStartedCb_ = null; | |
| 171 } | |
| 172 }, | |
| 173 | |
| 174 /** | |
| 135 * Shuts down and removes the plugin manager, if it exists. | 175 * Shuts down and removes the plugin manager, if it exists. |
| 136 * @private | 176 * @private |
| 137 */ | 177 */ |
| 138 shutdownPluginManager_: function() { | 178 shutdownPluginManager_: function() { |
| 139 if (this.pluginManager_) { | 179 if (this.pluginManager_) { |
| 140 this.pluginManager_.shutdown(); | 180 this.pluginManager_.shutdown(); |
| 141 this.pluginManager_ = null; | 181 this.pluginManager_ = null; |
| 142 } | 182 } |
| 143 }, | 183 }, |
| 144 | 184 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 156 * @private | 196 * @private |
| 157 */ | 197 */ |
| 158 onReady_: function() { | 198 onReady_: function() { |
| 159 if (this.state_ != State_.STARTING) { | 199 if (this.state_ != State_.STARTING) { |
| 160 // At this point, we should not be in the RUNNING state. Doing so would | 200 // At this point, we should not be in the RUNNING state. Doing so would |
| 161 // imply the hotword detector was started without being ready. | 201 // imply the hotword detector was started without being ready. |
| 162 assert(this.state_ != State_.RUNNING); | 202 assert(this.state_ != State_.RUNNING); |
| 163 this.shutdownPluginManager_(); | 203 this.shutdownPluginManager_(); |
| 164 return; | 204 return; |
| 165 } | 205 } |
| 166 this.state_ = State_.RUNNING; | 206 this.startRecognizer_(); |
| 167 this.pluginManager_.startRecognizer(); | |
| 168 }, | 207 }, |
| 169 | 208 |
| 170 /** | 209 /** |
| 171 * Handle an error from the hotword plugin. | 210 * Handle an error from the hotword plugin. |
| 172 * @private | 211 * @private |
| 173 */ | 212 */ |
| 174 onError_: function() { | 213 onError_: function() { |
| 175 this.state_ = State_.ERROR; | 214 this.state_ = State_.ERROR; |
| 176 this.shutdownPluginManager_(); | 215 this.shutdownPluginManager_(); |
| 177 }, | 216 }, |
| 178 | 217 |
| 179 /** | 218 /** |
| 180 * Handle hotword triggering. | 219 * Handle hotword triggering. |
| 181 * @private | 220 * @private |
| 182 */ | 221 */ |
| 183 onTrigger_: function() { | 222 onTrigger_: function() { |
| 184 assert(this.pluginManager_); | 223 assert(this.pluginManager_); |
| 185 // Detector implicitly stops when the hotword is detected. | 224 // Detector implicitly stops when the hotword is detected. |
| 186 this.state_ = State_.STOPPED; | 225 this.state_ = State_.STOPPED; |
| 187 | 226 |
| 188 chrome.hotwordPrivate.notifyHotwordRecognition('search', function() {}); | 227 chrome.hotwordPrivate.notifyHotwordRecognition('search', function() {}); |
| 228 | |
| 229 // Implicitly clear the session. A session needs to be started in order to | |
| 230 // restart the detector. | |
| 231 this.sessionSource_ = null; | |
| 232 this.sessionStartedCb_ = null; | |
| 233 }, | |
| 234 | |
| 235 /** | |
| 236 * Start a hotwording session. | |
| 237 * @param {!hotword.constants.SessionSource} source Source of the hotword | |
| 238 * session request. | |
| 239 * @param {!function()} started_cb Callback invoked when the session has | |
| 240 * been started successfully. | |
| 241 */ | |
| 242 startSession: function(source, started_cb) { | |
|
Dan Beam
2014/09/11 17:56:23
jsVarsLikeThis (not_like_cpp_vars)
Anand Mistry (off Chromium)
2014/09/12 00:43:33
Done.
| |
| 243 this.sessionSource_ = source; | |
| 244 this.sessionStartedCb_ = started_cb; | |
| 245 if (this.hotwordStatus_) | |
|
Dan Beam
2014/09/11 17:56:24
nit: maybe put
if (!this.hotwordStatus_)
re
Anand Mistry (off Chromium)
2014/09/12 00:43:33
Done.
| |
| 246 this.updateStateFromStatus_(); | |
| 247 }, | |
| 248 | |
| 249 /** | |
| 250 * Stops a hotwording session. | |
| 251 * @param {!hotword.constants.SessionSource} source Source of the hotword | |
| 252 * session request. | |
| 253 */ | |
| 254 stopSession: function(source) { | |
| 255 this.sessionSource_ = null; | |
| 256 this.sessionStartedCb_ = null; | |
| 257 if (this.hotwordStatus_) | |
| 258 this.updateStateFromStatus_(); | |
| 189 } | 259 } |
| 190 }; | 260 }; |
| 191 | 261 |
| 192 return { | 262 return { |
| 193 StateManager: StateManager | 263 StateManager: StateManager |
| 194 }; | 264 }; |
| 195 }); | 265 }); |
| OLD | NEW |