Chromium Code Reviews| Index: chrome/browser/resources/hotword/state_manager.js |
| diff --git a/chrome/browser/resources/hotword/state_manager.js b/chrome/browser/resources/hotword/state_manager.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..964e7dcf04abeb26bb26b57e7f31506253f9f33a |
| --- /dev/null |
| +++ b/chrome/browser/resources/hotword/state_manager.js |
| @@ -0,0 +1,184 @@ |
| +// Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +/** |
| + * @fileoverview Class to manage hotwording state. |
| + */ |
| + |
| +cr.define('hotword', function() { |
| +'use strict'; |
|
Dan Beam
2014/08/26 18:40:51
this code should probably be indented because it's
Anand Mistry (off Chromium)
2014/08/27 07:10:56
Done.
|
| + |
| +/** |
| + * @constructor |
| + * @struct |
| + */ |
| +function StateManager() { |
| + /** |
| + * Current state. |
| + * @private {hotword.StateManager.State_} |
| + */ |
| + this.state_ = State_.STOPPED; |
| + |
| + /** |
| + * Current hotwording status. |
| + * @private {chrome.hotwordPrivate.StatusDetails} |
| + */ |
| + this.hotwordStatus_ = null; |
| + |
| + /** |
| + * NaCl plugin manager. |
| + * @private {?hotword.NaClManager} |
|
Dan Beam
2014/08/26 18:40:51
add ? to |this.hotwordStatus_|'s type or remove fr
Anand Mistry (off Chromium)
2014/08/27 07:10:56
Done.
|
| + */ |
| + this.pluginManager_ = null; |
| + |
| + // Get the initial status. |
| + chrome.hotwordPrivate.getStatus(this.handleStatus_.bind(this)); |
| +} |
| + |
|
Dan Beam
2014/08/26 18:40:51
/**
* @enum {number}
* @private
*/
Anand Mistry (off Chromium)
2014/08/27 07:10:56
Done.
|
| +StateManager.State_ = { |
| + STOPPED: 0, |
| + STARTING: 1, |
| + RUNNING: 2, |
| + ERROR: 3, |
| +}; |
| +var State_ = StateManager.State_; |
| + |
| +/** |
| + * Request status details update. Intended to be called from the |
| + * hotwordPrivate.onEnabledChanged() event. |
| + */ |
| +StateManager.prototype.updateStatus = function() { |
| + chrome.hotwordPrivate.getStatus(this.handleStatus_.bind(this)); |
| +}; |
| + |
| +/** |
| + * Callback for hotwordPrivate.getStatus() function. |
| + * @param {chrome.hotwordPrivate.StatusDetails} status Current hotword status. |
| + * @private |
| + */ |
| +StateManager.prototype.handleStatus_ = function(status) { |
| + this.hotwordStatus_ = status; |
| + this.updateStateFromStatus_(); |
| +}; |
| + |
| +/** |
| + * Updates state based on the current status. |
| + * @private |
| + */ |
| +StateManager.prototype.updateStateFromStatus_ = function() { |
| + if (this.hotwordStatus_.enabled) { |
|
Dan Beam
2014/08/26 18:40:52
indent off (needs 1 more space)
Anand Mistry (off Chromium)
2014/08/27 07:10:56
WTF? How did that end up there? Done.
|
| + // Hotwording is enabled. |
| + // TODO(amistry): Have a separate alwaysOnEnabled flag. For now, treat |
| + // "enabled" as "always on enabled". |
| + this.startDetector_(); |
| + } else { |
| + // Not enabled. Shut down if running. |
| + this.shutdownDetector_(); |
| + } |
| +}; |
| + |
| +/** |
| + * Starts the hotword detector. |
| + * @private |
| + */ |
| +StateManager.prototype.startDetector_ = function() { |
| + // Last attempt to start detector resulted in an error. |
| + if (this.state_ == State_.ERROR) { |
| + // TODO(amistry): Do some error rate tracking here and disable the extension |
| + // if we error too often. |
|
Dan Beam
2014/08/26 18:40:52
is there some code you meant to put here?
Anand Mistry (off Chromium)
2014/08/27 07:10:56
Not yet. I'm not ready to fill in that kind of det
|
| + } |
| + |
| + if (this.pluginManager_ == null) { |
|
Dan Beam
2014/08/26 18:40:52
if (!this.pluginManager_) {
Anand Mistry (off Chromium)
2014/08/27 07:10:56
Done.
|
| + this.state_ = State_.STARTING; |
| + this.pluginManager_ = new hotword.NaClManager(); |
| + this.pluginManager_.addEventListener(hotword.constants.Event.READY, |
| + this.onReady_.bind(this)); |
|
Dan Beam
2014/08/26 18:40:52
indent off x 3
Anand Mistry (off Chromium)
2014/08/27 07:10:56
Done.
|
| + this.pluginManager_.addEventListener(hotword.constants.Event.ERROR, |
| + this.onError_.bind(this)); |
| + this.pluginManager_.addEventListener(hotword.constants.Event.TRIGGER, |
| + this.onTrigger_.bind(this)); |
| + chrome.runtime.getPlatformInfo(function(platform) { |
| + var naclArch = platform.nacl_arch; |
| + |
| + // googDucking set to false so that audio output level from other tabs is |
| + // not affected when hotword is enabled. https://crbug.com/357773 |
| + // src.chromium.org/svn/trunk/src/content/common/media/media_stream_options.cc |
|
Dan Beam
2014/08/26 18:40:52
use bit.ly or just put local path.
Anand Mistry (off Chromium)
2014/08/27 07:10:56
Done.
|
| + var constraints = /** @type {googMediaStreamConstraints} */ |
| + ({audio: {optional: [{ googDucking: false}] }}); |
|
Dan Beam
2014/08/26 18:40:52
no \s after { or }
Anand Mistry (off Chromium)
2014/08/27 07:10:56
Done.
|
| + navigator.webkitGetUserMedia( |
| + /** @type {MediaStreamConstraints} */ (constraints), |
| + function(stream) { |
| + if (!this.pluginManager_.initialize(naclArch, stream)) { |
| + this.state_ = State_.ERROR; |
| + this.pluginManager_.shutdown(); |
| + this.pluginManager_ = null; |
|
Dan Beam
2014/08/26 18:40:51
nit: this code seems to be repeated a lot:
this
Anand Mistry (off Chromium)
2014/08/27 07:10:56
Done.
|
| + } |
| + }.bind(this), |
| + function(error) { |
| + this.state_ = State_.ERROR; |
| + this.pluginManager_ = null; |
| + }.bind(this)); |
| + }.bind(this)); |
| + } else if (this.state_ != State_.STARTING) { |
| + // Don't try to start a starting detector. |
| + this.state_ = State_.RUNNING; |
| + this.pluginManager_.startRecognizer(); |
| + } |
| +}; |
| + |
| +/** |
| + * Shuts down the hotword detector. |
| + * @private |
| + */ |
| +StateManager.prototype.shutdownDetector_ = function() { |
| + this.state_ = State_.STOPPED; |
| + if (this.pluginManager_ != null) { |
| + this.pluginManager_.shutdown(); |
| + this.pluginManager_ = null; |
| + } |
| +}; |
| + |
| +/** |
| + * Handle the hotword plugin being ready to start. |
| + * @private |
| + */ |
| +StateManager.prototype.onReady_ = function() { |
| + if (this.state_ != State_.STARTING) { |
| + // Shouldn't be running while starting. |
| + assert(this.state_ != State_.RUNNING); |
| + this.pluginManager_.shutdown(); |
| + this.pluginManager_ = null; |
| + return; |
| + } |
| + this.state_ = State_.RUNNING; |
| + this.pluginManager_.startRecognizer(); |
| +}; |
| + |
| +/** |
| + * Handle an error from the hotword plugin. |
| + * @private |
| + */ |
| +StateManager.prototype.onError_ = function() { |
| + this.state_ = State_.ERROR; |
| + this.pluginManager_.shutdown(); |
| + this.pluginManager_ = null; |
| +}; |
| + |
| +/** |
| + * Handle hotword triggering. |
| + * @private |
| + */ |
| +StateManager.prototype.onTrigger_ = function() { |
| + assert(this.pluginManager_ != null); |
|
Dan Beam
2014/08/26 18:40:52
assert(this.pluginManager_)
Anand Mistry (off Chromium)
2014/08/27 07:10:56
Done.
|
| + // Detector implicitly stops when the hotword is detected. |
| + this.state_ = State_.STOPPED; |
| + |
| + chrome.hotwordPrivate.notifyHotwordRecognition('search', function() {}); |
| +}; |
| + |
| +return { |
| + StateManager: StateManager |
| +}; |
| + |
| +}); |