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.
9 * Class that keeps track of current burn process state.
10 * @param {Object} strings Localized state strings.
13 function State(strings
) {
14 this.setStrings(strings
);
15 this.changeState(State
.StatesEnum
.DEVICE_NONE
);
23 cssState
: 'device-detected-none',
26 cssState
: 'device-detected-usb warning',
29 cssState
: 'device-detected-sd warning',
32 cssState
: 'device-detected-mul warning',
35 cssState
: 'warning-no-conf',
37 ERROR_DEVICE_TOO_SMALL
: {
38 cssState
: 'warning-no-conf',
41 cssState
: 'progress progress-canceble',
44 cssState
: 'progress progress-canceble',
59 * Sets the state strings.
60 * @param {Object} strings Localized state strings.
62 setStrings: function(strings
) {
63 State
.StatesEnum
.DEVICE_NONE
.statusText
=
64 strings
.getString('statusDevicesNone');
65 State
.StatesEnum
.DEVICE_NONE
.warningText
=
66 strings
.getString('warningDevicesNone');
67 State
.StatesEnum
.DEVICE_USB
.statusText
=
68 strings
.getString('statusDeviceUSB');
69 State
.StatesEnum
.DEVICE_SD
.statusText
= strings
.getString('statusDeviceSD');
70 State
.StatesEnum
.DEVICE_MUL
.statusText
=
71 strings
.getString('statusDevicesMultiple');
72 State
.StatesEnum
.ERROR_NO_NETWORK
.statusText
=
73 strings
.getString('statusNoConnection');
74 State
.StatesEnum
.ERROR_NO_NETWORK
.warningText
=
75 strings
.getString('warningNoConnection');
76 State
.StatesEnum
.ERROR_DEVICE_TOO_SMALL
.statusText
=
77 strings
.getString('statusNoSpace');
78 State
.StatesEnum
.PROGRESS_DOWNLOAD
.statusText
=
79 strings
.getString('statusDownloading');
80 State
.StatesEnum
.PROGRESS_UNZIP
.statusText
=
81 strings
.getString('statusUnzip');
82 State
.StatesEnum
.PROGRESS_BURN
.statusText
= strings
.getString('statusBurn');
83 State
.StatesEnum
.FAIL
.statusText
= strings
.getString('statusError');
84 State
.StatesEnum
.SUCCESS
.statusText
= strings
.getString('statusSuccess');
85 State
.StatesEnum
.SUCCESS
.warningText
= strings
.getString('warningSuccess');
89 * Changes the current state to new state.
90 * @param {Object} newState Specifies the new state object.
92 changeState: function(newState
) {
93 if (newState
== this.state
)
95 this.state
= newState
;
97 $('main-content').className
= this.state
.cssState
;
99 $('status-text').textContent
= this.state
.statusText
;
101 if (newState
.warningText
)
102 $('warning-text').textContent
= this.state
.warningText
;
104 if (this.isInitialState() && this.state
!= State
.StatesEnum
.DEVICE_NONE
) {
105 $('warning-button').textContent
= localStrings
.getString('confirmButton');
106 } else if (this.state
== State
.StatesEnum
.FAIL
) {
107 $('warning-button').textContent
=
108 localStrings
.getString('retryButton');
113 * Reset to initial state.
114 * @param {Array} devices Array of device information.
116 gotoInitialState: function(devices
) {
117 if (devices
.length
== 0) {
118 this.changeState(State
.StatesEnum
.DEVICE_NONE
);
119 } else if (devices
.length
== 1) {
120 // If a device type is not specified for some reason, we should
121 // default to display a USB device.
122 var initialState
= State
.StatesEnum
.DEVICE_USB
;
123 if (devices
[0].type
== 'sd')
124 initialState
= State
.StatesEnum
.DEVICE_SD
;
125 this.changeState(initialState
);
127 this.changeState(State
.StatesEnum
.DEVICE_MUL
);
132 * Returns true if the device is in initial state.
133 * @return {boolean} True if the device is in initial state else false.
135 isInitialState: function() {
136 return this.state
== State
.StatesEnum
.DEVICE_NONE
||
137 this.state
== State
.StatesEnum
.DEVICE_USB
||
138 this.state
== State
.StatesEnum
.DEVICE_SD
||
139 this.state
== State
.StatesEnum
.DEVICE_MUL
;
143 * Returns true if device state matches the given state name.
144 * @param {string} stateName Given state name.
145 * @return {boolean} True if the device state matches the given state name.
147 equals: function(stateName
) {
148 return this.state
== stateName
;
153 * Class that keeps track of available devices.
156 function DeviceSelection() {
157 this.selectedDevice
= undefined;
161 DeviceSelection
.prototype = {
163 * Shows the currently selected device.
165 showDeviceSelection: function() {
166 if (this.devices
.length
== 0) {
167 this.selectedDevice
= undefined;
169 this.selectDevice(this.devices
[0].devicePath
);
174 * Handles device selected event.
175 * @param {string} label Device label.
176 * @param {string} filePath File path.
177 * @param {string} devicePath Selected device path.
179 onDeviceSelected: function(label
, filePath
, devicePath
) {
180 $('warning-button').onclick
=
181 browserBridge
.sendBurnImageMessage
.bind(browserBridge
, filePath
,
184 this.selectedDevice
= devicePath
;
186 $('warning-text').textContent
=
187 localStrings
.getStringF('warningDevices', label
);
191 * Selects the specified device based on the specified path.
192 * @param {string} path Device path.
194 selectDevice: function(path
) {
195 var element
= $('radio-' + path
);
196 element
.checked
= true;
197 element
.onclick
.apply(element
);
201 * Creates a new device element.
202 * @param {Object} device Specifies new device information.
203 * @return {HTMLLIElement} New device element.
205 createNewDeviceElement: function(device
) {
206 var element
= document
.createElement('li');
207 var radioButton
= document
.createElement('input');
208 radioButton
.type
= 'radio';
209 radioButton
.name
= 'device';
210 radioButton
.value
= device
.label
;
211 radioButton
.id
= 'radio-' + device
.devicePath
;
212 radioButton
.className
= 'float-start';
213 var deviceLabelText
= document
.createElement('p');
214 deviceLabelText
.textContent
= device
.label
;
215 deviceLabelText
.className
= 'select-option float-start';
216 var newLine
= document
.createElement('div');
217 newLine
.className
= 'new-line';
218 element
.appendChild(radioButton
);
219 element
.appendChild(deviceLabelText
);
220 element
.appendChild(newLine
);
221 element
.id
= 'select-' + device
.devicePath
;
222 element
.className
= 'selection-element';
223 radioButton
.onclick
= this.onDeviceSelected
.bind(this,
224 device
.label
, device
.filePath
, device
.devicePath
);
229 * Updates the list of selected devices.
230 * @param {Array} devices List of devices.
232 devicesUpdated: function(newDevices
) {
233 this.devices
= newDevices
;
234 var selectListDOM
= $('device-selection');
235 selectListDOM
.innerHTML
= '';
236 if (this.devices
.length
> 0) {
237 for (var i
= 0; i
< this.devices
.length
; i
++) {
238 var element
= this.createNewDeviceElement(this.devices
[i
]);
239 selectListDOM
.appendChild(element
);
241 this.selectDevice(this.devices
[0].devicePath
);
243 this.selectedDevice
= undefined;
248 * Handles device added event.
249 * @param {Object} device Device information.
250 * @param {boolean} allowSelect True to update the selected device info.
252 deviceAdded: function(device
, allowSelect
) {
253 this.devices
.push(device
);
254 var selectListDOM
= $('device-selection');
255 selectListDOM
.appendChild(this.createNewDeviceElement(device
));
256 if (allowSelect
&& this.devices
.length
== 1)
257 this.selectDevice(device
.devicePath
);
261 * Handles device removed event.
262 * @param {string} devicePath Device path to be removed.
263 * @param {boolean} allowSelect True to update the selected device info.
265 deviceRemoved: function(devicePath
, allowSelect
) {
266 device
= this.findDevice(devicePath
);
269 this.devices
.splice(this.devices
.indexOf(device
), 1);
271 // Remove device selection element from DOM.
272 var deviceSelectElement
= $('select-' + devicePath
);
273 deviceSelectElement
.parentNode
.removeChild(deviceSelectElement
);
275 // Update selected device element.
277 if (this.devices
.length
> 0) {
278 if (this.selectedDevice
== devicePath
)
279 this.selectDevice(this.devices
[0].devicePath
);
281 this.selectedDevice
= undefined;
287 * Finds device with given device path property.
288 * @param {string} devicePath Device path of device to find.
289 * @return {Object} Matching device information or undefined if not found.
291 findDevice: function(devicePath
) {
292 for (var i
= 0; i
< this.devices
.length
; ++i
) {
293 if (this.devices
[i
].devicePath
== devicePath
) {
294 return this.devices
[i
];
302 * Class that handles communication with chrome.
305 function BrowserBridge() {
306 this.currentState
= new State(localStrings
);
307 this.deviceSelection
= new DeviceSelection();
308 // We will use these often so it makes sence making them class members to
309 // avoid frequent document.getElementById calls.
310 this.progressElement
= $('progress-div');
311 this.progressText
= $('progress-text');
312 this.progressTimeLeftText
= $('pending-time');
315 BrowserBridge
.prototype = {
316 sendCancelMessage: function() {
317 chrome
.send('cancelBurnImage');
320 sendGetDevicesMessage: function() {
321 chrome
.send('getDevices');
324 sendWebuiInitializedMessage: function() {
325 chrome
.send('webuiInitialized');
329 * Sends the burn image message to c++ code.
330 * @param {string} filePath Specifies the file path.
331 * @param {string} devicePath Specifies the device path.
333 sendBurnImageMessage: function(filePath
, devicePath
) {
334 chrome
.send('burnImage', [devicePath
, filePath
]);
337 reportSuccess: function() {
338 this.currentState
.changeState(State
.StatesEnum
.SUCCESS
);
342 * Update the device state to report a failure and display an error message to
344 * @param {string} errorMessage Specifies the warning text message.
346 reportFail: function(errorMessage
) {
347 this.currentState
.changeState(State
.StatesEnum
.FAIL
);
348 $('warning-text').textContent
= errorMessage
;
349 $('warning-button').onclick
= this.onBurnRetry
.bind(this);
353 * Handles device added event.
354 * @param {Object} device Device information.
356 deviceAdded: function(device
) {
357 var inInitialState
= this.currentState
.isInitialState();
358 this.deviceSelection
.deviceAdded(device
, inInitialState
);
360 this.currentState
.gotoInitialState(this.deviceSelection
.devices
);
364 * Handles device removed event.
365 * @param {string} devicePath Device path to be removed.
367 deviceRemoved: function(devicePath
) {
368 var inInitialState
= this.currentState
.isInitialState();
369 this.deviceSelection
.deviceRemoved(devicePath
, inInitialState
);
371 this.currentState
.gotoInitialState(this.deviceSelection
.devices
);
375 * Gets device callbacks and update the current state.
376 * @param {Array} devices List of devices.
378 getDevicesCallback: function(devices
) {
379 this.deviceSelection
.devicesUpdated(devices
);
380 this.currentState
.gotoInitialState(this.deviceSelection
.devices
);
381 this.sendWebuiInitializedMessage();
385 * Updates the progress information based on the signal received.
386 * @param {Object} updateSignal Specifies the signal information.
388 updateProgress: function(updateSignal
) {
389 if (updateSignal
.progressType
== 'download' &&
390 !this.currentState
.equals(State
.StatesEnum
.PROGRESS_DOWNLOAD
)) {
391 this.currentState
.changeState(State
.StatesEnum
.PROGRESS_DOWNLOAD
);
392 } else if (updateSignal
.progressType
== 'unzip' &&
393 !this.currentState
.equals(State
.StatesEnum
.PROGRESS_UNZIP
)) {
394 this.currentState
.changeState(State
.StatesEnum
.PROGRESS_UNZIP
);
395 } else if (updateSignal
.progressType
== 'burn' &&
396 !this.currentState
.equals(State
.StatesEnum
.PROGRESS_BURN
)) {
397 this.currentState
.changeState(State
.StatesEnum
.PROGRESS_BURN
);
400 if (!(updateSignal
.amountTotal
> 0)) {
401 this.progressElement
.removeAttribute('value');
403 this.progressElement
.value
= updateSignal
.amountFinished
;
404 this.progressElement
.max
= updateSignal
.amountTotal
;
407 this.progressText
.textContent
= updateSignal
.progressText
;
408 this.progressTimeLeftText
.textContent
= updateSignal
.timeLeftText
;
411 reportNoNetwork: function() {
412 this.currentState
.changeState(State
.StatesEnum
.ERROR_NO_NETWORK
);
415 reportNetworkDetected: function() {
416 if (this.currentState
.equals(State
.StatesEnum
.ERROR_NO_NETWORK
)) {
417 this.deviceSelection
.showDeviceSelection();
418 this.currentState
.gotoInitialState(this.deviceSelection
.devices
);
423 * Updates the current state to report device too small error.
424 * @param {number} deviceSize Received device size.
426 reportDeviceTooSmall: function(deviceSize
) {
427 this.currentState
.changeState(State
.StatesEnum
.ERROR_DEVICE_TOO_SMALL
);
428 $('warning-text').textContent
=
429 localStrings
.getStringF('warningNoSpace', deviceSize
);
433 * Processes click on 'Retry' button in FAIL state.
435 onBurnRetry: function() {
436 this.deviceSelection
.showDeviceSelection();
437 this.currentState
.gotoInitialState(this.deviceSelection
.devices
);
441 document
.addEventListener('DOMContentLoaded', function() {
442 localStrings
= new LocalStrings();
443 browserBridge
= new BrowserBridge();
445 jstProcess(new JsEvalContext(templateData
), $('more-info-link'));
447 $('cancel-button').onclick
=
448 browserBridge
.sendCancelMessage
.bind(browserBridge
);
449 browserBridge
.sendGetDevicesMessage();