| 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 21 matching lines...) Expand all Loading... |
| 65 handleStatus_: function(status) { | 77 handleStatus_: function(status) { |
| 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() { |
| 87 if (!this.hotwordStatus_) |
| 88 return; |
| 89 |
| 75 if (this.hotwordStatus_.enabled) { | 90 if (this.hotwordStatus_.enabled) { |
| 76 // Hotwording is enabled. | 91 // 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 | 92 // isn't. |
| 78 // "enabled" as "always on enabled". | 93 // TODO(amistry): Support stacking sessions. This can happen when the |
| 79 this.startDetector_(); | 94 // user opens google.com or the NTP, then opens the launcher. Opening |
| 95 // google.com will create one session, and opening the launcher will |
| 96 // create the second. Closing the launcher should re-activate the |
| 97 // google.com session. |
| 98 // NOTE(amistry): With always-on, we want a different behaviour with |
| 99 // sessions since the detector should always be running. The exception |
| 100 // being when the user triggers by saying 'Ok Google'. In that case, the |
| 101 // detector stops, so starting/stopping the launcher session should |
| 102 // restart the detector. |
| 103 if (this.sessionSource_) |
| 104 this.startDetector_(); |
| 105 else |
| 106 this.shutdownDetector_(); |
| 80 } else { | 107 } else { |
| 81 // Not enabled. Shut down if running. | 108 // Not enabled. Shut down if running. |
| 82 this.shutdownDetector_(); | 109 this.shutdownDetector_(); |
| 83 } | 110 } |
| 84 }, | 111 }, |
| 85 | 112 |
| 86 /** | 113 /** |
| 87 * Starts the hotword detector. | 114 * Starts the hotword detector. |
| 88 * @private | 115 * @private |
| 89 */ | 116 */ |
| (...skipping 29 matching lines...) Expand all Loading... |
| 119 this.shutdownPluginManager_(); | 146 this.shutdownPluginManager_(); |
| 120 } | 147 } |
| 121 }.bind(this), | 148 }.bind(this), |
| 122 function(error) { | 149 function(error) { |
| 123 this.state_ = State_.ERROR; | 150 this.state_ = State_.ERROR; |
| 124 this.pluginManager_ = null; | 151 this.pluginManager_ = null; |
| 125 }.bind(this)); | 152 }.bind(this)); |
| 126 }.bind(this)); | 153 }.bind(this)); |
| 127 } else if (this.state_ != State_.STARTING) { | 154 } else if (this.state_ != State_.STARTING) { |
| 128 // Don't try to start a starting detector. | 155 // Don't try to start a starting detector. |
| 129 this.state_ = State_.RUNNING; | 156 this.startRecognizer_(); |
| 130 this.pluginManager_.startRecognizer(); | |
| 131 } | 157 } |
| 132 }, | 158 }, |
| 133 | 159 |
| 134 /** | 160 /** |
| 161 * Start the recognizer plugin. Assumes the plugin has been loaded and is |
| 162 * ready to start. |
| 163 * @private |
| 164 */ |
| 165 startRecognizer_: function() { |
| 166 assert(this.pluginManager_); |
| 167 if (this.state_ != State_.RUNNING) { |
| 168 this.state_ = State_.RUNNING; |
| 169 this.pluginManager_.startRecognizer(); |
| 170 } |
| 171 if (this.sessionStartedCb_) { |
| 172 this.sessionStartedCb_(); |
| 173 this.sessionStartedCb_ = null; |
| 174 } |
| 175 }, |
| 176 |
| 177 /** |
| 135 * Shuts down and removes the plugin manager, if it exists. | 178 * Shuts down and removes the plugin manager, if it exists. |
| 136 * @private | 179 * @private |
| 137 */ | 180 */ |
| 138 shutdownPluginManager_: function() { | 181 shutdownPluginManager_: function() { |
| 139 if (this.pluginManager_) { | 182 if (this.pluginManager_) { |
| 140 this.pluginManager_.shutdown(); | 183 this.pluginManager_.shutdown(); |
| 141 this.pluginManager_ = null; | 184 this.pluginManager_ = null; |
| 142 } | 185 } |
| 143 }, | 186 }, |
| 144 | 187 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 156 * @private | 199 * @private |
| 157 */ | 200 */ |
| 158 onReady_: function() { | 201 onReady_: function() { |
| 159 if (this.state_ != State_.STARTING) { | 202 if (this.state_ != State_.STARTING) { |
| 160 // At this point, we should not be in the RUNNING state. Doing so would | 203 // At this point, we should not be in the RUNNING state. Doing so would |
| 161 // imply the hotword detector was started without being ready. | 204 // imply the hotword detector was started without being ready. |
| 162 assert(this.state_ != State_.RUNNING); | 205 assert(this.state_ != State_.RUNNING); |
| 163 this.shutdownPluginManager_(); | 206 this.shutdownPluginManager_(); |
| 164 return; | 207 return; |
| 165 } | 208 } |
| 166 this.state_ = State_.RUNNING; | 209 this.startRecognizer_(); |
| 167 this.pluginManager_.startRecognizer(); | |
| 168 }, | 210 }, |
| 169 | 211 |
| 170 /** | 212 /** |
| 171 * Handle an error from the hotword plugin. | 213 * Handle an error from the hotword plugin. |
| 172 * @private | 214 * @private |
| 173 */ | 215 */ |
| 174 onError_: function() { | 216 onError_: function() { |
| 175 this.state_ = State_.ERROR; | 217 this.state_ = State_.ERROR; |
| 176 this.shutdownPluginManager_(); | 218 this.shutdownPluginManager_(); |
| 177 }, | 219 }, |
| 178 | 220 |
| 179 /** | 221 /** |
| 180 * Handle hotword triggering. | 222 * Handle hotword triggering. |
| 181 * @private | 223 * @private |
| 182 */ | 224 */ |
| 183 onTrigger_: function() { | 225 onTrigger_: function() { |
| 184 assert(this.pluginManager_); | 226 assert(this.pluginManager_); |
| 185 // Detector implicitly stops when the hotword is detected. | 227 // Detector implicitly stops when the hotword is detected. |
| 186 this.state_ = State_.STOPPED; | 228 this.state_ = State_.STOPPED; |
| 187 | 229 |
| 188 chrome.hotwordPrivate.notifyHotwordRecognition('search', function() {}); | 230 chrome.hotwordPrivate.notifyHotwordRecognition('search', function() {}); |
| 231 |
| 232 // Implicitly clear the session. A session needs to be started in order to |
| 233 // restart the detector. |
| 234 this.sessionSource_ = null; |
| 235 this.sessionStartedCb_ = null; |
| 236 }, |
| 237 |
| 238 /** |
| 239 * Start a hotwording session. |
| 240 * @param {!hotword.constants.SessionSource} source Source of the hotword |
| 241 * session request. |
| 242 * @param {!function()} startedCb Callback invoked when the session has |
| 243 * been started successfully. |
| 244 */ |
| 245 startSession: function(source, startedCb) { |
| 246 this.sessionSource_ = source; |
| 247 this.sessionStartedCb_ = startedCb; |
| 248 this.updateStateFromStatus_(); |
| 249 }, |
| 250 |
| 251 /** |
| 252 * Stops a hotwording session. |
| 253 * @param {!hotword.constants.SessionSource} source Source of the hotword |
| 254 * session request. |
| 255 */ |
| 256 stopSession: function(source) { |
| 257 this.sessionSource_ = null; |
| 258 this.sessionStartedCb_ = null; |
| 259 this.updateStateFromStatus_(); |
| 189 } | 260 } |
| 190 }; | 261 }; |
| 191 | 262 |
| 192 return { | 263 return { |
| 193 StateManager: StateManager | 264 StateManager: StateManager |
| 194 }; | 265 }; |
| 195 }); | 266 }); |
| OLD | NEW |