1 // Copyright (c) 2012 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.
8 * Class that keeps track of current burn process state.
9 * @param {Object} strings Localized state strings.
12 function State(strings) {
13 this.setStrings(strings);
14 this.changeState(State.StatesEnum.DEVICE_NONE);
22 cssState: 'device-detected-none',
25 cssState: 'device-detected-usb warning',
28 cssState: 'device-detected-sd warning',
31 cssState: 'device-detected-mul warning',
34 cssState: 'warning-no-conf',
36 ERROR_DEVICE_TOO_SMALL: {
37 cssState: 'warning-no-conf',
40 cssState: 'progress progress-canceble',
43 cssState: 'progress progress-canceble',
58 * Sets the state strings.
59 * @param {Object} strings Localized state strings.
61 setStrings: function(strings) {
62 State.StatesEnum.DEVICE_NONE.statusText =
63 strings.getString('statusDevicesNone');
64 State.StatesEnum.DEVICE_NONE.warningText =
65 strings.getString('warningDevicesNone');
66 State.StatesEnum.DEVICE_USB.statusText =
67 strings.getString('statusDeviceUSB');
68 State.StatesEnum.DEVICE_SD.statusText = strings.getString('statusDeviceSD');
69 State.StatesEnum.DEVICE_MUL.statusText =
70 strings.getString('statusDevicesMultiple');
71 State.StatesEnum.ERROR_NO_NETWORK.statusText =
72 strings.getString('statusNoConnection');
73 State.StatesEnum.ERROR_NO_NETWORK.warningText =
74 strings.getString('warningNoConnection');
75 State.StatesEnum.ERROR_DEVICE_TOO_SMALL.statusText =
76 strings.getString('statusNoSpace');
77 State.StatesEnum.PROGRESS_DOWNLOAD.statusText =
78 strings.getString('statusDownloading');
79 State.StatesEnum.PROGRESS_UNZIP.statusText =
80 strings.getString('statusUnzip');
81 State.StatesEnum.PROGRESS_BURN.statusText = strings.getString('statusBurn');
82 State.StatesEnum.FAIL.statusText = strings.getString('statusError');
83 State.StatesEnum.SUCCESS.statusText = strings.getString('statusSuccess');
84 State.StatesEnum.SUCCESS.warningText = strings.getString('warningSuccess');
88 * Changes the current state to new state.
89 * @param {Object} newState Specifies the new state object.
91 changeState: function(newState) {
92 if (newState == this.state)
94 this.state = newState;
96 $('main-content').className = this.state.cssState;
98 $('status-text').textContent = this.state.statusText;
100 if (newState.warningText)
101 $('warning-text').textContent = this.state.warningText;
103 if (this.isInitialState() && this.state != State.StatesEnum.DEVICE_NONE) {
104 $('warning-button').textContent = loadTimeData.getString('confirmButton');
105 } else if (this.state == State.StatesEnum.FAIL) {
106 $('warning-button').textContent =
107 loadTimeData.getString('retryButton');
112 * Reset to initial state.
113 * @param {Array} devices Array of device information.
115 gotoInitialState: function(devices) {
116 if (devices.length == 0) {
117 this.changeState(State.StatesEnum.DEVICE_NONE);
118 } else if (devices.length == 1) {
119 // If a device type is not specified for some reason, we should
120 // default to display a USB device.
121 var initialState = State.StatesEnum.DEVICE_USB;
122 if (devices[0].type == 'sd')
123 initialState = State.StatesEnum.DEVICE_SD;
124 this.changeState(initialState);
126 this.changeState(State.StatesEnum.DEVICE_MUL);
131 * Returns true if the device is in initial state.
132 * @return {boolean} True if the device is in initial state else false.
134 isInitialState: function() {
135 return this.state == State.StatesEnum.DEVICE_NONE ||
136 this.state == State.StatesEnum.DEVICE_USB ||
137 this.state == State.StatesEnum.DEVICE_SD ||
138 this.state == State.StatesEnum.DEVICE_MUL;
142 * Returns true if device state matches the given state name.
143 * @param {string} stateName Given state name.
144 * @return {boolean} True if the device state matches the given state name.
146 equals: function(stateName) {
147 return this.state == stateName;
152 * Class that keeps track of available devices.
155 function DeviceSelection() {
156 this.selectedDevice = undefined;
160 DeviceSelection.prototype = {
162 * Shows the currently selected device.
164 showDeviceSelection: function() {
165 if (this.devices.length == 0) {
166 this.selectedDevice = undefined;
168 this.selectDevice(this.devices[0].devicePath);
173 * Handles device selected event.
174 * @param {string} label Device label.
175 * @param {string} filePath File path.
176 * @param {string} devicePath Selected device path.
178 onDeviceSelected: function(label, filePath, devicePath) {
179 $('warning-button').onclick =
180 browserBridge.sendBurnImageMessage.bind(browserBridge, filePath,
183 this.selectedDevice = devicePath;
185 $('warning-text').textContent =
186 loadTimeData.getStringF('warningDevices', label);
190 * Selects the specified device based on the specified path.
191 * @param {string} path Device path.
193 selectDevice: function(path) {
194 var element = $('radio-' + path);
195 element.checked = true;
196 element.onclick.apply(element);
200 * Creates a new device element.
201 * @param {Object} device Specifies new device information.
202 * @return {HTMLLIElement} New device element.
204 createNewDeviceElement: function(device) {
205 var element = document.createElement('li');
206 var radioButton = document.createElement('input');
207 radioButton.type = 'radio';
208 radioButton.name = 'device';
209 radioButton.value = device.label;
210 radioButton.id = 'radio-' + device.devicePath;
211 radioButton.className = 'float-start';
212 var deviceLabelText = document.createElement('p');
213 deviceLabelText.textContent = device.label;
214 deviceLabelText.className = 'select-option float-start';
215 var newLine = document.createElement('div');
216 newLine.className = 'new-line';
217 element.appendChild(radioButton);
218 element.appendChild(deviceLabelText);
219 element.appendChild(newLine);
220 element.id = 'select-' + device.devicePath;
221 element.className = 'selection-element';
222 radioButton.onclick = this.onDeviceSelected.bind(this,
223 device.label, device.filePath, device.devicePath);
228 * Updates the list of selected devices.
229 * @param {Array} devices List of devices.
231 devicesUpdated: function(newDevices) {
232 this.devices = newDevices;
233 var selectListDOM = $('device-selection');
234 selectListDOM.innerHTML = '';
235 if (this.devices.length > 0) {
236 for (var i = 0; i < this.devices.length; i++) {
237 var element = this.createNewDeviceElement(this.devices[i]);
238 selectListDOM.appendChild(element);
240 this.selectDevice(this.devices[0].devicePath);
242 this.selectedDevice = undefined;
247 * Handles device added event.
248 * @param {Object} device Device information.
249 * @param {boolean} allowSelect True to update the selected device info.
251 deviceAdded: function(device, allowSelect) {
252 this.devices.push(device);
253 var selectListDOM = $('device-selection');
254 selectListDOM.appendChild(this.createNewDeviceElement(device));
255 if (allowSelect && this.devices.length == 1)
256 this.selectDevice(device.devicePath);
260 * Handles device removed event.
261 * @param {string} devicePath Device path to be removed.
262 * @param {boolean} allowSelect True to update the selected device info.
264 deviceRemoved: function(devicePath, allowSelect) {
265 device = this.findDevice(devicePath);
268 this.devices.splice(this.devices.indexOf(device), 1);
270 // Remove device selection element from DOM.
271 var deviceSelectElement = $('select-' + devicePath);
272 deviceSelectElement.parentNode.removeChild(deviceSelectElement);
274 // Update selected device element.
276 if (this.devices.length > 0) {
277 if (this.selectedDevice == devicePath)
278 this.selectDevice(this.devices[0].devicePath);
280 this.selectedDevice = undefined;
286 * Finds device with given device path property.
287 * @param {string} devicePath Device path of device to find.
288 * @return {Object} Matching device information or undefined if not found.
290 findDevice: function(devicePath) {
291 for (var i = 0; i < this.devices.length; ++i) {
292 if (this.devices[i].devicePath == devicePath) {
293 return this.devices[i];
301 * Class that handles communication with chrome.
304 function BrowserBridge() {
305 this.currentState = new State(loadTimeData);
306 this.deviceSelection = new DeviceSelection();
307 // We will use these often so it makes sence making them class members to
308 // avoid frequent document.getElementById calls.
309 this.progressElement = $('progress-div');
310 this.progressText = $('progress-text');
311 this.progressTimeLeftText = $('pending-time');
314 BrowserBridge.prototype = {
315 sendCancelMessage: function() {
316 chrome.send('cancelBurnImage');
319 sendGetDevicesMessage: function() {
320 chrome.send('getDevices');
323 sendWebuiInitializedMessage: function() {
324 chrome.send('webuiInitialized');
328 * Sends the burn image message to c++ code.
329 * @param {string} filePath Specifies the file path.
330 * @param {string} devicePath Specifies the device path.
332 sendBurnImageMessage: function(filePath, devicePath) {
333 chrome.send('burnImage', [devicePath, filePath]);
336 reportSuccess: function() {
337 this.currentState.changeState(State.StatesEnum.SUCCESS);
341 * Update the device state to report a failure and display an error message to
343 * @param {string} errorMessage Specifies the warning text message.
345 reportFail: function(errorMessage) {
346 this.currentState.changeState(State.StatesEnum.FAIL);
347 $('warning-text').textContent = errorMessage;
348 $('warning-button').onclick = this.onBurnRetry.bind(this);
352 * Handles device added event.
353 * @param {Object} device Device information.
355 deviceAdded: function(device) {
356 var inInitialState = this.currentState.isInitialState();
357 this.deviceSelection.deviceAdded(device, inInitialState);
359 this.currentState.gotoInitialState(this.deviceSelection.devices);
363 * Handles device removed event.
364 * @param {string} devicePath Device path to be removed.
366 deviceRemoved: function(devicePath) {
367 var inInitialState = this.currentState.isInitialState();
368 this.deviceSelection.deviceRemoved(devicePath, inInitialState);
370 this.currentState.gotoInitialState(this.deviceSelection.devices);
374 * Gets device callbacks and update the current state.
375 * @param {Array} devices List of devices.
377 getDevicesCallback: function(devices) {
378 this.deviceSelection.devicesUpdated(devices);
379 this.currentState.gotoInitialState(this.deviceSelection.devices);
380 this.sendWebuiInitializedMessage();
384 * Updates the progress information based on the signal received.
385 * @param {Object} updateSignal Specifies the signal information.
387 updateProgress: function(updateSignal) {
388 if (updateSignal.progressType == 'download' &&
389 !this.currentState.equals(State.StatesEnum.PROGRESS_DOWNLOAD)) {
390 this.currentState.changeState(State.StatesEnum.PROGRESS_DOWNLOAD);
391 } else if (updateSignal.progressType == 'unzip' &&
392 !this.currentState.equals(State.StatesEnum.PROGRESS_UNZIP)) {
393 this.currentState.changeState(State.StatesEnum.PROGRESS_UNZIP);
394 } else if (updateSignal.progressType == 'burn' &&
395 !this.currentState.equals(State.StatesEnum.PROGRESS_BURN)) {
396 this.currentState.changeState(State.StatesEnum.PROGRESS_BURN);
399 if (!(updateSignal.amountTotal > 0)) {
400 this.progressElement.removeAttribute('value');
402 this.progressElement.value = updateSignal.amountFinished;
403 this.progressElement.max = updateSignal.amountTotal;
406 this.progressText.textContent = updateSignal.progressText;
407 this.progressTimeLeftText.textContent = updateSignal.timeLeftText;
410 reportNoNetwork: function() {
411 this.currentState.changeState(State.StatesEnum.ERROR_NO_NETWORK);
414 reportNetworkDetected: function() {
415 if (this.currentState.equals(State.StatesEnum.ERROR_NO_NETWORK)) {
416 this.deviceSelection.showDeviceSelection();
417 this.currentState.gotoInitialState(this.deviceSelection.devices);
422 * Updates the current state to report device too small error.
423 * @param {number} deviceSize Received device size.
425 reportDeviceTooSmall: function(deviceSize) {
426 this.currentState.changeState(State.StatesEnum.ERROR_DEVICE_TOO_SMALL);
427 $('warning-text').textContent =
428 loadTimeData.getStringF('warningNoSpace', deviceSize);
432 * Processes click on 'Retry' button in FAIL state.
434 onBurnRetry: function() {
435 this.deviceSelection.showDeviceSelection();
436 this.currentState.gotoInitialState(this.deviceSelection.devices);
440 document.addEventListener('DOMContentLoaded', function() {
441 browserBridge = new BrowserBridge();
443 $('cancel-button').onclick =
444 browserBridge.sendCancelMessage.bind(browserBridge);
445 browserBridge.sendGetDevicesMessage();