Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: chrome/browser/resources/hotword/state_manager.js

Issue 493203004: Add a StateManager for managing hotwording state based on various factors (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@hotword-nacl-manager
Patch Set: Rebase. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/resources/hotword/manifest.json ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 cr.define('hotword', function() {
6 'use strict';
7
8 /**
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
11 * whether or not hotwording should be running.
12 * @constructor
13 * @struct
14 */
15 function StateManager() {
16 /**
17 * Current state.
18 * @private {hotword.StateManager.State_}
19 */
20 this.state_ = State_.STOPPED;
21
22 /**
23 * Current hotwording status.
24 * @private {?chrome.hotwordPrivate.StatusDetails}
25 */
26 this.hotwordStatus_ = null;
27
28 /**
29 * NaCl plugin manager.
30 * @private {?hotword.NaClManager}
31 */
32 this.pluginManager_ = null;
33
34 // Get the initial status.
35 chrome.hotwordPrivate.getStatus(this.handleStatus_.bind(this));
36 }
37
38 /**
39 * @enum {number}
40 * @private
41 */
42 StateManager.State_ = {
43 STOPPED: 0,
44 STARTING: 1,
45 RUNNING: 2,
46 ERROR: 3,
47 };
48 var State_ = StateManager.State_;
49
50 StateManager.prototype = {
51 /**
52 * Request status details update. Intended to be called from the
53 * hotwordPrivate.onEnabledChanged() event.
54 */
55 updateStatus: function() {
56 chrome.hotwordPrivate.getStatus(this.handleStatus_.bind(this));
57 },
58
59 /**
60 * Callback for hotwordPrivate.getStatus() function.
61 * @param {chrome.hotwordPrivate.StatusDetails} status Current hotword
62 * status.
63 * @private
64 */
65 handleStatus_: function(status) {
66 this.hotwordStatus_ = status;
67 this.updateStateFromStatus_();
68 },
69
70 /**
71 * Updates state based on the current status.
72 * @private
73 */
74 updateStateFromStatus_: function() {
75 if (this.hotwordStatus_.enabled) {
76 // Hotwording is enabled.
77 // TODO(amistry): Have a separate alwaysOnEnabled flag. For now, treat
78 // "enabled" as "always on enabled".
79 this.startDetector_();
80 } else {
81 // Not enabled. Shut down if running.
82 this.shutdownDetector_();
83 }
84 },
85
86 /**
87 * Starts the hotword detector.
88 * @private
89 */
90 startDetector_: function() {
91 // Last attempt to start detector resulted in an error.
92 if (this.state_ == State_.ERROR) {
93 // TODO(amistry): Do some error rate tracking here and disable the
94 // extension if we error too often.
95 }
96
97 if (!this.pluginManager_) {
98 this.state_ = State_.STARTING;
99 this.pluginManager_ = new hotword.NaClManager();
100 this.pluginManager_.addEventListener(hotword.constants.Event.READY,
101 this.onReady_.bind(this));
102 this.pluginManager_.addEventListener(hotword.constants.Event.ERROR,
103 this.onError_.bind(this));
104 this.pluginManager_.addEventListener(hotword.constants.Event.TRIGGER,
105 this.onTrigger_.bind(this));
106 chrome.runtime.getPlatformInfo(function(platform) {
107 var naclArch = platform.nacl_arch;
108
109 // googDucking set to false so that audio output level from other tabs
110 // is not affected when hotword is enabled. https://crbug.com/357773
111 // content/common/media/media_stream_options.cc
112 var constraints = /** @type {googMediaStreamConstraints} */
113 ({audio: {optional: [{googDucking: false}]}});
114 navigator.webkitGetUserMedia(
115 /** @type {MediaStreamConstraints} */ (constraints),
116 function(stream) {
117 if (!this.pluginManager_.initialize(naclArch, stream)) {
118 this.state_ = State_.ERROR;
119 this.shutdownPluginManager_();
120 }
121 }.bind(this),
122 function(error) {
123 this.state_ = State_.ERROR;
124 this.pluginManager_ = null;
125 }.bind(this));
126 }.bind(this));
127 } else if (this.state_ != State_.STARTING) {
128 // Don't try to start a starting detector.
129 this.state_ = State_.RUNNING;
130 this.pluginManager_.startRecognizer();
131 }
132 },
133
134 /**
135 * Shuts down and removes the plugin manager, if it exists.
136 * @private
137 */
138 shutdownPluginManager_: function() {
139 if (this.pluginManager_) {
140 this.pluginManager_.shutdown();
141 this.pluginManager_ = null;
142 }
143 },
144
145 /**
146 * Shuts down the hotword detector.
147 * @private
148 */
149 shutdownDetector_: function() {
150 this.state_ = State_.STOPPED;
151 this.shutdownPluginManager_();
152 },
153
154 /**
155 * Handle the hotword plugin being ready to start.
156 * @private
157 */
158 onReady_: function() {
159 if (this.state_ != State_.STARTING) {
160 // At this point, we should not be in the RUNNING state. Doing so would
161 // imply the hotword detector was started without being ready.
162 assert(this.state_ != State_.RUNNING);
163 this.shutdownPluginManager_();
164 return;
165 }
166 this.state_ = State_.RUNNING;
167 this.pluginManager_.startRecognizer();
168 },
169
170 /**
171 * Handle an error from the hotword plugin.
172 * @private
173 */
174 onError_: function() {
175 this.state_ = State_.ERROR;
176 this.shutdownPluginManager_();
177 },
178
179 /**
180 * Handle hotword triggering.
181 * @private
182 */
183 onTrigger_: function() {
184 assert(this.pluginManager_);
185 // Detector implicitly stops when the hotword is detected.
186 this.state_ = State_.STOPPED;
187
188 chrome.hotwordPrivate.notifyHotwordRecognition('search', function() {});
189 }
190 };
191
192 return {
193 StateManager: StateManager
194 };
195 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/hotword/manifest.json ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698