Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / chromeos / image_burner.js
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.
4
5 var browserBridge;
6
7 /**
8  * Class that keeps track of current burn process state.
9  * @param {Object} strings Localized state strings.
10  * @constructor
11  */
12 function State(strings) {
13   this.setStrings(strings);
14   this.changeState(State.StatesEnum.DEVICE_NONE);
15 }
16
17 /**
18  * State Enum object.
19  */
20 State.StatesEnum = {
21   DEVICE_NONE: {
22     cssState: 'device-detected-none',
23   },
24   DEVICE_USB: {
25     cssState: 'device-detected-usb warning',
26   },
27   DEVICE_SD: {
28     cssState: 'device-detected-sd warning',
29   },
30   DEVICE_MUL: {
31     cssState: 'device-detected-mul warning',
32   },
33   ERROR_NO_NETWORK: {
34     cssState: 'warning-no-conf',
35   },
36   ERROR_DEVICE_TOO_SMALL: {
37     cssState: 'warning-no-conf',
38   },
39   PROGRESS_DOWNLOAD: {
40     cssState: 'progress progress-canceble',
41   },
42   PROGRESS_UNZIP: {
43     cssState: 'progress progress-canceble',
44   },
45   PROGRESS_BURN: {
46     cssState: 'progress',
47   },
48   FAIL: {
49     cssState: 'error',
50   },
51   SUCCESS: {
52     cssState: 'success',
53   },
54 };
55
56 State.prototype = {
57   /**
58    * Sets the state strings.
59    * @param {Object} strings Localized state strings.
60    */
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');
85   },
86
87   /**
88    * Changes the current state to new state.
89    * @param {Object} newState Specifies the new state object.
90    */
91   changeState: function(newState) {
92     if (newState == this.state)
93       return;
94     this.state = newState;
95
96     $('main-content').className = this.state.cssState;
97
98     $('status-text').textContent = this.state.statusText;
99
100     if (newState.warningText)
101       $('warning-text').textContent = this.state.warningText;
102
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');
108     }
109   },
110
111   /**
112    * Reset to initial state.
113    * @param {Array} devices Array of device information.
114    */
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);
125     } else {
126       this.changeState(State.StatesEnum.DEVICE_MUL);
127     }
128   },
129
130   /**
131    * Returns true if the device is in initial state.
132    * @return {boolean} True if the device is in initial state else false.
133    */
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;
139   },
140
141   /**
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.
145    */
146   equals: function(stateName) {
147     return this.state == stateName;
148   }
149 };
150
151 /**
152  * Class that keeps track of available devices.
153  * @constructor
154  */
155 function DeviceSelection() {
156   this.selectedDevice = undefined;
157   this.devices = [];
158 }
159
160 DeviceSelection.prototype = {
161   /**
162    * Shows the currently selected device.
163    */
164   showDeviceSelection: function() {
165     if (this.devices.length == 0) {
166       this.selectedDevice = undefined;
167     } else {
168       this.selectDevice(this.devices[0].devicePath);
169     }
170   },
171
172   /**
173    * Handles device selected event.
174    * @param {string} label Device label.
175    * @param {string} filePath File path.
176    * @param {string} devicePath Selected device path.
177    */
178   onDeviceSelected: function(label, filePath, devicePath) {
179     $('warning-button').onclick =
180         browserBridge.sendBurnImageMessage.bind(browserBridge, filePath,
181             devicePath);
182
183     this.selectedDevice = devicePath;
184
185     $('warning-text').textContent =
186         loadTimeData.getStringF('warningDevices', label);
187   },
188
189   /**
190    * Selects the specified device based on the specified path.
191    * @param {string} path Device path.
192    */
193   selectDevice: function(path) {
194     var element = $('radio-' + path);
195     element.checked = true;
196     element.onclick.apply(element);
197   },
198
199   /**
200    * Creates a new device element.
201    * @param {Object} device Specifies new device information.
202    * @return {HTMLLIElement} New device element.
203    */
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);
224     return element;
225   },
226
227   /**
228    * Updates the list of selected devices.
229    * @param {Array} devices List of devices.
230    */
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);
239       }
240       this.selectDevice(this.devices[0].devicePath);
241     } else {
242       this.selectedDevice = undefined;
243     }
244   },
245
246   /**
247    * Handles device added event.
248    * @param {Object} device Device information.
249    * @param {boolean} allowSelect True to update the selected device info.
250    */
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);
257   },
258
259   /**
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.
263    */
264   deviceRemoved: function(devicePath, allowSelect) {
265     device = this.findDevice(devicePath);
266     if (!device)
267       return;
268     this.devices.splice(this.devices.indexOf(device), 1);
269
270     // Remove device selection element from DOM.
271     var deviceSelectElement = $('select-' + devicePath);
272     deviceSelectElement.parentNode.removeChild(deviceSelectElement);
273
274     // Update selected device element.
275     if (allowSelect) {
276       if (this.devices.length > 0) {
277         if (this.selectedDevice == devicePath)
278           this.selectDevice(this.devices[0].devicePath);
279       } else {
280         this.selectedDevice = undefined;
281       }
282     }
283   },
284
285   /**
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.
289    */
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];
294       }
295     }
296     return undefined;
297   }
298 };
299
300 /**
301  * Class that handles communication with chrome.
302  * @constructor
303  */
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');
312 }
313
314 BrowserBridge.prototype = {
315   sendCancelMessage: function() {
316     chrome.send('cancelBurnImage');
317   },
318
319   sendGetDevicesMessage: function() {
320     chrome.send('getDevices');
321   },
322
323   sendWebuiInitializedMessage: function() {
324     chrome.send('webuiInitialized');
325   },
326
327   /**
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.
331    */
332   sendBurnImageMessage: function(filePath, devicePath) {
333     chrome.send('burnImage', [devicePath, filePath]);
334   },
335
336   reportSuccess: function() {
337     this.currentState.changeState(State.StatesEnum.SUCCESS);
338   },
339
340   /**
341    * Update the device state to report a failure and display an error message to
342    * the user.
343    * @param {string} errorMessage Specifies the warning text message.
344    */
345   reportFail: function(errorMessage) {
346     this.currentState.changeState(State.StatesEnum.FAIL);
347     $('warning-text').textContent = errorMessage;
348     $('warning-button').onclick = this.onBurnRetry.bind(this);
349   },
350
351   /**
352    * Handles device added event.
353    * @param {Object} device Device information.
354    */
355   deviceAdded: function(device) {
356     var inInitialState = this.currentState.isInitialState();
357     this.deviceSelection.deviceAdded(device, inInitialState);
358     if (inInitialState)
359       this.currentState.gotoInitialState(this.deviceSelection.devices);
360   },
361
362   /**
363    * Handles device removed event.
364    * @param {string} devicePath Device path to be removed.
365    */
366   deviceRemoved: function(devicePath) {
367     var inInitialState = this.currentState.isInitialState();
368     this.deviceSelection.deviceRemoved(devicePath, inInitialState);
369     if (inInitialState)
370       this.currentState.gotoInitialState(this.deviceSelection.devices);
371   },
372
373   /**
374    * Gets device callbacks and update the current state.
375    * @param {Array} devices List of devices.
376    */
377   getDevicesCallback: function(devices) {
378     this.deviceSelection.devicesUpdated(devices);
379     this.currentState.gotoInitialState(this.deviceSelection.devices);
380     this.sendWebuiInitializedMessage();
381   },
382
383   /**
384    *  Updates the progress information based on the signal received.
385    *  @param {Object} updateSignal Specifies the signal information.
386    */
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);
397     }
398
399     if (!(updateSignal.amountTotal > 0)) {
400       this.progressElement.removeAttribute('value');
401     } else {
402       this.progressElement.value = updateSignal.amountFinished;
403       this.progressElement.max = updateSignal.amountTotal;
404     }
405
406     this.progressText.textContent = updateSignal.progressText;
407     this.progressTimeLeftText.textContent = updateSignal.timeLeftText;
408   },
409
410   reportNoNetwork: function() {
411     this.currentState.changeState(State.StatesEnum.ERROR_NO_NETWORK);
412   },
413
414   reportNetworkDetected: function() {
415     if (this.currentState.equals(State.StatesEnum.ERROR_NO_NETWORK)) {
416       this.deviceSelection.showDeviceSelection();
417       this.currentState.gotoInitialState(this.deviceSelection.devices);
418     }
419   },
420
421   /**
422    *  Updates the current state to report device too small error.
423    *  @param {number} deviceSize Received device size.
424    */
425   reportDeviceTooSmall: function(deviceSize) {
426     this.currentState.changeState(State.StatesEnum.ERROR_DEVICE_TOO_SMALL);
427     $('warning-text').textContent =
428         loadTimeData.getStringF('warningNoSpace', deviceSize);
429   },
430
431   /**
432    * Processes click on 'Retry' button in FAIL state.
433    */
434   onBurnRetry: function() {
435     this.deviceSelection.showDeviceSelection();
436     this.currentState.gotoInitialState(this.deviceSelection.devices);
437   }
438 };
439
440 document.addEventListener('DOMContentLoaded', function() {
441   browserBridge = new BrowserBridge();
442
443   $('cancel-button').onclick =
444       browserBridge.sendCancelMessage.bind(browserBridge);
445   browserBridge.sendGetDevicesMessage();
446 });