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..25000e8c7cec198931b915321c4e59f871ae5cd5 |
| --- /dev/null |
| +++ b/chrome/browser/resources/hotword/state_manager.js |
| @@ -0,0 +1,193 @@ |
| +// 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. |
|
Dan Beam
2014/08/27 20:08:37
nit: if it fits, one-liner -- /** ... */
Dan Beam
2014/08/27 20:08:37
this isn't a particularly useful comment and shoul
Anand Mistry (off Chromium)
2014/08/28 00:59:26
Done.
|
| + */ |
| + |
|
Dan Beam
2014/08/27 20:08:37
remove \n
Anand Mistry (off Chromium)
2014/08/28 00:59:26
Done.
|
| +cr.define('hotword', function() { |
| + 'use strict'; |
| + |
| + /** |
| + * @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} |
| + */ |
| + this.pluginManager_ = null; |
| + |
| + // Get the initial status. |
| + chrome.hotwordPrivate.getStatus(this.handleStatus_.bind(this)); |
| + } |
| + |
| + /** |
| + * @enum {number} |
| + * @private |
| + */ |
| + 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() { |
|
Dan Beam
2014/08/27 20:08:37
nit: just assign whole prototype
StateManager.p
Anand Mistry (off Chromium)
2014/08/28 00:59:25
Done.
|
| + 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) { |
| + // 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. |
| + } |
| + |
| + if (!this.pluginManager_) { |
| + this.state_ = State_.STARTING; |
| + this.pluginManager_ = new hotword.NaClManager(); |
| + this.pluginManager_.addEventListener(hotword.constants.Event.READY, |
| + this.onReady_.bind(this)); |
| + 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 |
| + // content/common/media/media_stream_options.cc |
| + var constraints = /** @type {googMediaStreamConstraints} */ |
| + ({audio: {optional: [{googDucking: false}]}}); |
| + navigator.webkitGetUserMedia( |
| + /** @type {MediaStreamConstraints} */ (constraints), |
| + function(stream) { |
| + if (!this.pluginManager_.initialize(naclArch, stream)) { |
| + this.state_ = State_.ERROR; |
| + this.shutdownPluginManager_(); |
| + } |
| + }.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 and removes the plugin manager, if it exists. |
| + * @private |
| + */ |
| + StateManager.prototype.shutdownPluginManager_ = function() { |
| + if (this.pluginManager_) { |
| + this.pluginManager_.shutdown(); |
| + this.pluginManager_ = null; |
| + } |
| + }; |
| + |
| + /** |
| + * Shuts down the hotword detector. |
| + * @private |
| + */ |
| + StateManager.prototype.shutdownDetector_ = function() { |
| + this.state_ = State_.STOPPED; |
| + this.shutdownPluginManager_(); |
| + }; |
| + |
| + /** |
| + * Handle the hotword plugin being ready to start. |
| + * @private |
| + */ |
| + StateManager.prototype.onReady_ = function() { |
| + if (this.state_ != State_.STARTING) { |
| + // Shouldn't be running while starting. |
|
Dan Beam
2014/08/27 20:08:37
this comment is confusing because you say the code
Anand Mistry (off Chromium)
2014/08/28 00:59:26
Done.
|
| + assert(this.state_ != State_.RUNNING); |
| + this.shutdownPluginManager_(); |
| + 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.shutdownPluginManager_(); |
| + }; |
| + |
| + /** |
| + * Handle hotword triggering. |
| + * @private |
| + */ |
| + StateManager.prototype.onTrigger_ = function() { |
| + assert(this.pluginManager_); |
| + // Detector implicitly stops when the hotword is detected. |
| + this.state_ = State_.STOPPED; |
| + |
| + chrome.hotwordPrivate.notifyHotwordRecognition('search', function() {}); |
| + }; |
| + |
| + return { |
| + StateManager: StateManager |
| + }; |
| + |
|
Dan Beam
2014/08/27 20:08:37
nit: remove \n
Anand Mistry (off Chromium)
2014/08/28 00:59:25
Done.
|
| +}); |