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

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

Issue 2939273002: DO NOT SUBMIT: what chrome/browser/resources/ could eventually look like with clang-format (Closed)
Patch Set: Created 3 years, 6 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 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 'use strict'; 5 'use strict';
6 6
7 /* eslint-disable no-restricted-properties */ 7 /* eslint-disable no-restricted-properties */
8 8
9 /** 9 /**
10 * @fileoverview This is the audio client content script injected into eligible 10 * @fileoverview This is the audio client content script injected into eligible
11 * Google.com and New tab pages for interaction between the Webpage and the 11 * Google.com and New tab pages for interaction between the Webpage and the
12 * Hotword extension. 12 * Hotword extension.
13 */ 13 */
14 14
15 (function() { 15 (function() {
16 /**
17 * @constructor
18 */
19 var AudioClient = function() {
20 /** @private {Element} */
21 this.speechOverlay_ = null;
22
23 /** @private {number} */
24 this.checkSpeechUiRetries_ = 0;
25
16 /** 26 /**
17 * @constructor 27 * Port used to communicate with the audio manager.
28 * @private {?Port}
18 */ 29 */
19 var AudioClient = function() { 30 this.port_ = null;
20 /** @private {Element} */ 31
21 this.speechOverlay_ = null; 32 /**
22 33 * Keeps track of the effects of different commands. Used to verify that
23 /** @private {number} */ 34 * proper UIs are shown to the user.
35 * @private {Object<AudioClient.CommandToPage, Object>}
36 */
37 this.uiStatus_ = null;
38
39 /**
40 * Bound function used to handle commands sent from the page to this script.
41 * @private {Function}
42 */
43 this.handleCommandFromPageFunc_ = null;
44 };
45
46 /**
47 * Messages sent to the page to control the voice search UI.
48 * @enum {string}
49 */
50 AudioClient.CommandToPage = {
51 HOTWORD_VOICE_TRIGGER: 'vt',
52 HOTWORD_STARTED: 'hs',
53 HOTWORD_ENDED: 'hd',
54 HOTWORD_TIMEOUT: 'ht',
55 HOTWORD_ERROR: 'he'
56 };
57
58 /**
59 * Messages received from the page used to indicate voice search state.
60 * @enum {string}
61 */
62 AudioClient.CommandFromPage = {
63 SPEECH_START: 'ss',
64 SPEECH_END: 'se',
65 SPEECH_RESET: 'sr',
66 SHOWING_HOTWORD_START: 'shs',
67 SHOWING_ERROR_MESSAGE: 'sem',
68 SHOWING_TIMEOUT_MESSAGE: 'stm',
69 CLICKED_RESUME: 'hcc',
70 CLICKED_RESTART: 'hcr',
71 CLICKED_DEBUG: 'hcd'
72 };
73
74 /**
75 * Errors that are sent to the hotword extension.
76 * @enum {string}
77 */
78 AudioClient.Error = {
79 NO_SPEECH_UI: 'ac1',
80 NO_HOTWORD_STARTED_UI: 'ac2',
81 NO_HOTWORD_TIMEOUT_UI: 'ac3',
82 NO_HOTWORD_ERROR_UI: 'ac4'
83 };
84
85 /**
86 * @const {string}
87 * @private
88 */
89 AudioClient.HOTWORD_EXTENSION_ID_ = 'nbpagnldghgfoolbancepceaanlmhfmd';
90
91 /**
92 * Number of times to retry checking a transient error.
93 * @const {number}
94 * @private
95 */
96 AudioClient.MAX_RETRIES = 3;
97
98 /**
99 * Delay to wait in milliseconds before rechecking for any transient errors.
100 * @const {number}
101 * @private
102 */
103 AudioClient.RETRY_TIME_MS_ = 2000;
104
105 /**
106 * DOM ID for the speech UI overlay.
107 * @const {string}
108 * @private
109 */
110 AudioClient.SPEECH_UI_OVERLAY_ID_ = 'spch';
111
112 /**
113 * @const {string}
114 * @private
115 */
116 AudioClient.HELP_CENTER_URL_ =
117 'https://support.google.com/chrome/?p=ui_hotword_search';
118
119 /**
120 * @const {string}
121 * @private
122 */
123 AudioClient.CLIENT_PORT_NAME_ = 'chwcpn';
124
125 /**
126 * Existence of the Audio Client.
127 * @const {string}
128 * @private
129 */
130 AudioClient.EXISTS_ = 'chwace';
131
132 /**
133 * Checks for the presence of speech overlay UI DOM elements.
134 * @private
135 */
136 AudioClient.prototype.checkSpeechOverlayUi_ = function() {
137 if (!this.speechOverlay_) {
138 window.setTimeout(
139 this.delayedCheckSpeechOverlayUi_.bind(this),
140 AudioClient.RETRY_TIME_MS_);
141 } else {
24 this.checkSpeechUiRetries_ = 0; 142 this.checkSpeechUiRetries_ = 0;
25 143 }
26 /** 144 };
27 * Port used to communicate with the audio manager. 145
28 * @private {?Port} 146 /**
29 */ 147 * Function called to check for the speech UI overlay after some time has
30 this.port_ = null; 148 * passed since an initial check. Will either retry triggering the speech
31 149 * or sends an error message depending on the number of retries.
32 /** 150 * @private
33 * Keeps track of the effects of different commands. Used to verify that 151 */
34 * proper UIs are shown to the user. 152 AudioClient.prototype.delayedCheckSpeechOverlayUi_ = function() {
35 * @private {Object<AudioClient.CommandToPage, Object>} 153 this.speechOverlay_ =
36 */ 154 document.getElementById(AudioClient.SPEECH_UI_OVERLAY_ID_);
37 this.uiStatus_ = null; 155 if (!this.speechOverlay_) {
38 156 if (this.checkSpeechUiRetries_++ < AudioClient.MAX_RETRIES) {
39 /** 157 this.sendCommandToPage_(AudioClient.CommandToPage.VOICE_TRIGGER);
40 * Bound function used to handle commands sent from the page to this script. 158 this.checkSpeechOverlayUi_();
41 * @private {Function} 159 } else {
42 */ 160 this.sendCommandToExtension_(AudioClient.Error.NO_SPEECH_UI);
43 this.handleCommandFromPageFunc_ = null; 161 }
162 } else {
163 this.checkSpeechUiRetries_ = 0;
164 }
165 };
166
167 /**
168 * Checks that the triggered UI is actually displayed.
169 * @param {AudioClient.CommandToPage} command Command that was send.
170 * @private
171 */
172 AudioClient.prototype.checkUi_ = function(command) {
173 this.uiStatus_[command].timeoutId = window.setTimeout(
174 this.failedCheckUi_.bind(this, command), AudioClient.RETRY_TIME_MS_);
175 };
176
177 /**
178 * Function called when the UI verification is not called in time. Will either
179 * retry the command or sends an error message, depending on the number of
180 * retries for the command.
181 * @param {AudioClient.CommandToPage} command Command that was sent.
182 * @private
183 */
184 AudioClient.prototype.failedCheckUi_ = function(command) {
185 if (this.uiStatus_[command].tries++ < AudioClient.MAX_RETRIES) {
186 this.sendCommandToPage_(command);
187 this.checkUi_(command);
188 } else {
189 this.sendCommandToExtension_(this.uiStatus_[command].error);
190 }
191 };
192
193 /**
194 * Confirm that an UI element has been shown.
195 * @param {AudioClient.CommandToPage} command UI to confirm.
196 * @private
197 */
198 AudioClient.prototype.verifyUi_ = function(command) {
199 if (this.uiStatus_[command].timeoutId) {
200 window.clearTimeout(this.uiStatus_[command].timeoutId);
201 this.uiStatus_[command].timeoutId = null;
202 this.uiStatus_[command].tries = 0;
203 }
204 };
205
206 /**
207 * Sends a command to the audio manager.
208 * @param {string} commandStr command to send to plugin.
209 * @private
210 */
211 AudioClient.prototype.sendCommandToExtension_ = function(commandStr) {
212 if (this.port_)
213 this.port_.postMessage({'cmd': commandStr});
214 };
215
216 /**
217 * Handles a message from the audio manager.
218 * @param {{cmd: string}} commandObj Command from the audio manager.
219 * @private
220 */
221 AudioClient.prototype.handleCommandFromExtension_ = function(commandObj) {
222 var command = commandObj['cmd'];
223 if (command) {
224 switch (command) {
225 case AudioClient.CommandToPage.HOTWORD_VOICE_TRIGGER:
226 this.sendCommandToPage_(command);
227 this.checkSpeechOverlayUi_();
228 break;
229 case AudioClient.CommandToPage.HOTWORD_STARTED:
230 this.sendCommandToPage_(command);
231 this.checkUi_(command);
232 break;
233 case AudioClient.CommandToPage.HOTWORD_ENDED:
234 this.sendCommandToPage_(command);
235 break;
236 case AudioClient.CommandToPage.HOTWORD_TIMEOUT:
237 this.sendCommandToPage_(command);
238 this.checkUi_(command);
239 break;
240 case AudioClient.CommandToPage.HOTWORD_ERROR:
241 this.sendCommandToPage_(command);
242 this.checkUi_(command);
243 break;
244 }
245 }
246 };
247
248 /**
249 * @param {AudioClient.CommandToPage} commandStr Command to send.
250 * @private
251 */
252 AudioClient.prototype.sendCommandToPage_ = function(commandStr) {
253 window.postMessage({'type': commandStr}, '*');
254 };
255
256 /**
257 * Handles a message from the html window.
258 * @param {!MessageEvent} messageEvent Message event from the window.
259 * @private
260 */
261 AudioClient.prototype.handleCommandFromPage_ = function(messageEvent) {
262 if (messageEvent.source == window && messageEvent.data.type) {
263 var command = messageEvent.data.type;
264 switch (command) {
265 case AudioClient.CommandFromPage.SPEECH_START:
266 this.speechActive_ = true;
267 this.sendCommandToExtension_(command);
268 break;
269 case AudioClient.CommandFromPage.SPEECH_END:
270 this.speechActive_ = false;
271 this.sendCommandToExtension_(command);
272 break;
273 case AudioClient.CommandFromPage.SPEECH_RESET:
274 this.speechActive_ = false;
275 this.sendCommandToExtension_(command);
276 break;
277 case 'SPEECH_RESET': // Legacy, for embedded NTP.
278 this.speechActive_ = false;
279 this.sendCommandToExtension_(AudioClient.CommandFromPage.SPEECH_END);
280 break;
281 case AudioClient.CommandFromPage.CLICKED_RESUME:
282 this.sendCommandToExtension_(command);
283 break;
284 case AudioClient.CommandFromPage.CLICKED_RESTART:
285 this.sendCommandToExtension_(command);
286 break;
287 case AudioClient.CommandFromPage.CLICKED_DEBUG:
288 window.open(AudioClient.HELP_CENTER_URL_, '_blank');
289 break;
290 case AudioClient.CommandFromPage.SHOWING_HOTWORD_START:
291 this.verifyUi_(AudioClient.CommandToPage.HOTWORD_STARTED);
292 break;
293 case AudioClient.CommandFromPage.SHOWING_ERROR_MESSAGE:
294 this.verifyUi_(AudioClient.CommandToPage.HOTWORD_ERROR);
295 break;
296 case AudioClient.CommandFromPage.SHOWING_TIMEOUT_MESSAGE:
297 this.verifyUi_(AudioClient.CommandToPage.HOTWORD_TIMEOUT);
298 break;
299 }
300 }
301 };
302
303 /**
304 * Initialize the content script.
305 */
306 AudioClient.prototype.initialize = function() {
307 if (AudioClient.EXISTS_ in window)
308 return;
309 window[AudioClient.EXISTS_] = true;
310
311 // UI verification object.
312 this.uiStatus_ = {};
313 this.uiStatus_[AudioClient.CommandToPage.HOTWORD_STARTED] = {
314 timeoutId: null,
315 tries: 0,
316 error: AudioClient.Error.NO_HOTWORD_STARTED_UI
44 }; 317 };
45 318 this.uiStatus_[AudioClient.CommandToPage.HOTWORD_TIMEOUT] = {
46 /** 319 timeoutId: null,
47 * Messages sent to the page to control the voice search UI. 320 tries: 0,
48 * @enum {string} 321 error: AudioClient.Error.NO_HOTWORD_TIMEOUT_UI
49 */
50 AudioClient.CommandToPage = {
51 HOTWORD_VOICE_TRIGGER: 'vt',
52 HOTWORD_STARTED: 'hs',
53 HOTWORD_ENDED: 'hd',
54 HOTWORD_TIMEOUT: 'ht',
55 HOTWORD_ERROR: 'he'
56 }; 322 };
57 323 this.uiStatus_[AudioClient.CommandToPage.HOTWORD_ERROR] = {
58 /** 324 timeoutId: null,
59 * Messages received from the page used to indicate voice search state. 325 tries: 0,
60 * @enum {string} 326 error: AudioClient.Error.NO_HOTWORD_ERROR_UI
61 */
62 AudioClient.CommandFromPage = {
63 SPEECH_START: 'ss',
64 SPEECH_END: 'se',
65 SPEECH_RESET: 'sr',
66 SHOWING_HOTWORD_START: 'shs',
67 SHOWING_ERROR_MESSAGE: 'sem',
68 SHOWING_TIMEOUT_MESSAGE: 'stm',
69 CLICKED_RESUME: 'hcc',
70 CLICKED_RESTART: 'hcr',
71 CLICKED_DEBUG: 'hcd'
72 }; 327 };
73 328
74 /** 329 this.handleCommandFromPageFunc_ = this.handleCommandFromPage_.bind(this);
75 * Errors that are sent to the hotword extension. 330 window.addEventListener('message', this.handleCommandFromPageFunc_, false);
76 * @enum {string} 331 this.initPort_();
77 */ 332 };
78 AudioClient.Error = { 333
79 NO_SPEECH_UI: 'ac1', 334 /**
80 NO_HOTWORD_STARTED_UI: 'ac2', 335 * Initialize the communications port with the audio manager. This
81 NO_HOTWORD_TIMEOUT_UI: 'ac3', 336 * function will be also be called again if the audio-manager
82 NO_HOTWORD_ERROR_UI: 'ac4' 337 * disconnects for some reason (such as the extension
83 }; 338 * background.html page being reloaded).
84 339 * @private
85 /** 340 */
86 * @const {string} 341 AudioClient.prototype.initPort_ = function() {
87 * @private 342 this.port_ = chrome.runtime.connect(
88 */ 343 AudioClient.HOTWORD_EXTENSION_ID_,
89 AudioClient.HOTWORD_EXTENSION_ID_ = 'nbpagnldghgfoolbancepceaanlmhfmd'; 344 {'name': AudioClient.CLIENT_PORT_NAME_});
90 345 // Note that this listen may have to be destroyed manually if AudioClient
91 /** 346 // is ever destroyed on this tab.
92 * Number of times to retry checking a transient error. 347 this.port_.onDisconnect.addListener(
93 * @const {number} 348 (function(e) {
94 * @private 349 if (this.handleCommandFromPageFunc_) {
95 */ 350 window.removeEventListener(
96 AudioClient.MAX_RETRIES = 3; 351 'message', this.handleCommandFromPageFunc_, false);
97 352 }
98 /** 353 delete window[AudioClient.EXISTS_];
99 * Delay to wait in milliseconds before rechecking for any transient errors. 354 }).bind(this));
100 * @const {number} 355
101 * @private 356 // See note above.
102 */ 357 this.port_.onMessage.addListener(this.handleCommandFromExtension_.bind(this));
103 AudioClient.RETRY_TIME_MS_ = 2000; 358
104 359 if (this.speechActive_) {
105 /** 360 this.sendCommandToExtension_(AudioClient.CommandFromPage.SPEECH_START);
106 * DOM ID for the speech UI overlay. 361 } else {
107 * @const {string} 362 // It's possible for this script to be injected into the page after it has
108 * @private 363 // completed loaded (i.e. when prerendering). In this case, this script
109 */ 364 // won't receive a SPEECH_RESET from the page to forward onto the
110 AudioClient.SPEECH_UI_OVERLAY_ID_ = 'spch'; 365 // extension. To make up for this, always send a SPEECH_RESET. This means
111 366 // in most cases, the extension will receive SPEECH_RESET twice, one from
112 /** 367 // this sendCommandToExtension_ and the one forwarded from the page. But
113 * @const {string} 368 // that's OK and the extension can handle it.
114 * @private 369 this.sendCommandToExtension_(AudioClient.CommandFromPage.SPEECH_RESET);
115 */ 370 }
116 AudioClient.HELP_CENTER_URL_ = 371 };
117 'https://support.google.com/chrome/?p=ui_hotword_search'; 372
118 373 // Initializes as soon as the code is ready, do not wait for the page.
119 /** 374 new AudioClient().initialize();
120 * @const {string}
121 * @private
122 */
123 AudioClient.CLIENT_PORT_NAME_ = 'chwcpn';
124
125 /**
126 * Existence of the Audio Client.
127 * @const {string}
128 * @private
129 */
130 AudioClient.EXISTS_ = 'chwace';
131
132 /**
133 * Checks for the presence of speech overlay UI DOM elements.
134 * @private
135 */
136 AudioClient.prototype.checkSpeechOverlayUi_ = function() {
137 if (!this.speechOverlay_) {
138 window.setTimeout(
139 this.delayedCheckSpeechOverlayUi_.bind(this),
140 AudioClient.RETRY_TIME_MS_);
141 } else {
142 this.checkSpeechUiRetries_ = 0;
143 }
144 };
145
146 /**
147 * Function called to check for the speech UI overlay after some time has
148 * passed since an initial check. Will either retry triggering the speech
149 * or sends an error message depending on the number of retries.
150 * @private
151 */
152 AudioClient.prototype.delayedCheckSpeechOverlayUi_ = function() {
153 this.speechOverlay_ =
154 document.getElementById(AudioClient.SPEECH_UI_OVERLAY_ID_);
155 if (!this.speechOverlay_) {
156 if (this.checkSpeechUiRetries_++ < AudioClient.MAX_RETRIES) {
157 this.sendCommandToPage_(AudioClient.CommandToPage.VOICE_TRIGGER);
158 this.checkSpeechOverlayUi_();
159 } else {
160 this.sendCommandToExtension_(AudioClient.Error.NO_SPEECH_UI);
161 }
162 } else {
163 this.checkSpeechUiRetries_ = 0;
164 }
165 };
166
167 /**
168 * Checks that the triggered UI is actually displayed.
169 * @param {AudioClient.CommandToPage} command Command that was send.
170 * @private
171 */
172 AudioClient.prototype.checkUi_ = function(command) {
173 this.uiStatus_[command].timeoutId = window.setTimeout(
174 this.failedCheckUi_.bind(this, command), AudioClient.RETRY_TIME_MS_);
175 };
176
177 /**
178 * Function called when the UI verification is not called in time. Will either
179 * retry the command or sends an error message, depending on the number of
180 * retries for the command.
181 * @param {AudioClient.CommandToPage} command Command that was sent.
182 * @private
183 */
184 AudioClient.prototype.failedCheckUi_ = function(command) {
185 if (this.uiStatus_[command].tries++ < AudioClient.MAX_RETRIES) {
186 this.sendCommandToPage_(command);
187 this.checkUi_(command);
188 } else {
189 this.sendCommandToExtension_(this.uiStatus_[command].error);
190 }
191 };
192
193 /**
194 * Confirm that an UI element has been shown.
195 * @param {AudioClient.CommandToPage} command UI to confirm.
196 * @private
197 */
198 AudioClient.prototype.verifyUi_ = function(command) {
199 if (this.uiStatus_[command].timeoutId) {
200 window.clearTimeout(this.uiStatus_[command].timeoutId);
201 this.uiStatus_[command].timeoutId = null;
202 this.uiStatus_[command].tries = 0;
203 }
204 };
205
206 /**
207 * Sends a command to the audio manager.
208 * @param {string} commandStr command to send to plugin.
209 * @private
210 */
211 AudioClient.prototype.sendCommandToExtension_ = function(commandStr) {
212 if (this.port_)
213 this.port_.postMessage({'cmd': commandStr});
214 };
215
216 /**
217 * Handles a message from the audio manager.
218 * @param {{cmd: string}} commandObj Command from the audio manager.
219 * @private
220 */
221 AudioClient.prototype.handleCommandFromExtension_ = function(commandObj) {
222 var command = commandObj['cmd'];
223 if (command) {
224 switch (command) {
225 case AudioClient.CommandToPage.HOTWORD_VOICE_TRIGGER:
226 this.sendCommandToPage_(command);
227 this.checkSpeechOverlayUi_();
228 break;
229 case AudioClient.CommandToPage.HOTWORD_STARTED:
230 this.sendCommandToPage_(command);
231 this.checkUi_(command);
232 break;
233 case AudioClient.CommandToPage.HOTWORD_ENDED:
234 this.sendCommandToPage_(command);
235 break;
236 case AudioClient.CommandToPage.HOTWORD_TIMEOUT:
237 this.sendCommandToPage_(command);
238 this.checkUi_(command);
239 break;
240 case AudioClient.CommandToPage.HOTWORD_ERROR:
241 this.sendCommandToPage_(command);
242 this.checkUi_(command);
243 break;
244 }
245 }
246 };
247
248 /**
249 * @param {AudioClient.CommandToPage} commandStr Command to send.
250 * @private
251 */
252 AudioClient.prototype.sendCommandToPage_ = function(commandStr) {
253 window.postMessage({'type': commandStr}, '*');
254 };
255
256 /**
257 * Handles a message from the html window.
258 * @param {!MessageEvent} messageEvent Message event from the window.
259 * @private
260 */
261 AudioClient.prototype.handleCommandFromPage_ = function(messageEvent) {
262 if (messageEvent.source == window && messageEvent.data.type) {
263 var command = messageEvent.data.type;
264 switch (command) {
265 case AudioClient.CommandFromPage.SPEECH_START:
266 this.speechActive_ = true;
267 this.sendCommandToExtension_(command);
268 break;
269 case AudioClient.CommandFromPage.SPEECH_END:
270 this.speechActive_ = false;
271 this.sendCommandToExtension_(command);
272 break;
273 case AudioClient.CommandFromPage.SPEECH_RESET:
274 this.speechActive_ = false;
275 this.sendCommandToExtension_(command);
276 break;
277 case 'SPEECH_RESET': // Legacy, for embedded NTP.
278 this.speechActive_ = false;
279 this.sendCommandToExtension_(AudioClient.CommandFromPage.SPEECH_END);
280 break;
281 case AudioClient.CommandFromPage.CLICKED_RESUME:
282 this.sendCommandToExtension_(command);
283 break;
284 case AudioClient.CommandFromPage.CLICKED_RESTART:
285 this.sendCommandToExtension_(command);
286 break;
287 case AudioClient.CommandFromPage.CLICKED_DEBUG:
288 window.open(AudioClient.HELP_CENTER_URL_, '_blank');
289 break;
290 case AudioClient.CommandFromPage.SHOWING_HOTWORD_START:
291 this.verifyUi_(AudioClient.CommandToPage.HOTWORD_STARTED);
292 break;
293 case AudioClient.CommandFromPage.SHOWING_ERROR_MESSAGE:
294 this.verifyUi_(AudioClient.CommandToPage.HOTWORD_ERROR);
295 break;
296 case AudioClient.CommandFromPage.SHOWING_TIMEOUT_MESSAGE:
297 this.verifyUi_(AudioClient.CommandToPage.HOTWORD_TIMEOUT);
298 break;
299 }
300 }
301 };
302
303 /**
304 * Initialize the content script.
305 */
306 AudioClient.prototype.initialize = function() {
307 if (AudioClient.EXISTS_ in window)
308 return;
309 window[AudioClient.EXISTS_] = true;
310
311 // UI verification object.
312 this.uiStatus_ = {};
313 this.uiStatus_[AudioClient.CommandToPage.HOTWORD_STARTED] = {
314 timeoutId: null,
315 tries: 0,
316 error: AudioClient.Error.NO_HOTWORD_STARTED_UI
317 };
318 this.uiStatus_[AudioClient.CommandToPage.HOTWORD_TIMEOUT] = {
319 timeoutId: null,
320 tries: 0,
321 error: AudioClient.Error.NO_HOTWORD_TIMEOUT_UI
322 };
323 this.uiStatus_[AudioClient.CommandToPage.HOTWORD_ERROR] = {
324 timeoutId: null,
325 tries: 0,
326 error: AudioClient.Error.NO_HOTWORD_ERROR_UI
327 };
328
329 this.handleCommandFromPageFunc_ = this.handleCommandFromPage_.bind(this);
330 window.addEventListener('message', this.handleCommandFromPageFunc_, false);
331 this.initPort_();
332 };
333
334 /**
335 * Initialize the communications port with the audio manager. This
336 * function will be also be called again if the audio-manager
337 * disconnects for some reason (such as the extension
338 * background.html page being reloaded).
339 * @private
340 */
341 AudioClient.prototype.initPort_ = function() {
342 this.port_ = chrome.runtime.connect(
343 AudioClient.HOTWORD_EXTENSION_ID_,
344 {'name': AudioClient.CLIENT_PORT_NAME_});
345 // Note that this listen may have to be destroyed manually if AudioClient
346 // is ever destroyed on this tab.
347 this.port_.onDisconnect.addListener(
348 (function(e) {
349 if (this.handleCommandFromPageFunc_) {
350 window.removeEventListener(
351 'message', this.handleCommandFromPageFunc_, false);
352 }
353 delete window[AudioClient.EXISTS_];
354 }).bind(this));
355
356 // See note above.
357 this.port_.onMessage.addListener(
358 this.handleCommandFromExtension_.bind(this));
359
360 if (this.speechActive_) {
361 this.sendCommandToExtension_(AudioClient.CommandFromPage.SPEECH_START);
362 } else {
363 // It's possible for this script to be injected into the page after it has
364 // completed loaded (i.e. when prerendering). In this case, this script
365 // won't receive a SPEECH_RESET from the page to forward onto the
366 // extension. To make up for this, always send a SPEECH_RESET. This means
367 // in most cases, the extension will receive SPEECH_RESET twice, one from
368 // this sendCommandToExtension_ and the one forwarded from the page. But
369 // that's OK and the extension can handle it.
370 this.sendCommandToExtension_(AudioClient.CommandFromPage.SPEECH_RESET);
371 }
372 };
373
374 // Initializes as soon as the code is ready, do not wait for the page.
375 new AudioClient().initialize();
376 })(); 375 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698