1 /*
  2  * This is system cordova_plugin (TV specific API).
  3  * Apache License (2004). See http://www.apache.org/licenses/LICENSE-2.0
  4  *
  5  * Copyright (c) 2014, LG Electronics, Inc.
  6  */
  7 
  8 
  9 /**
 10  * This represents the FileManager API itself, and provides a global namespace for operating FileManager service.
 11  * FileManager will be used to manage files in internal memory.
 12  * 
 13  * To locate a resource for file system APIs, SCAP URI is used.
 14  * SCAP URI has following format.
 15  * 
 16  * @class
 17  */
 18 
 19 cordova.define('cordova/plugin/storage', function (require, exports, module) { // jshint ignore:line
 20 	var service;
 21 	function log(msg){
 22 	    //console.log//will be removed // jshint ignore:line
 23 	}
 24 	if(window.PalmSystem){ // jshint ignore:line
 25 		log("Window.PalmSystem Available");
 26 		service = require('cordova/plugin/webos/service');
 27 	}
 28 	else{
 29 		service = {
 30 				Request : function(uri, params){
 31 					log(uri + " invoked. But I am a dummy because PalmSystem is not available");
 32 					if(typeof params.onFailure === 'function'){
 33 						params.onFailure({returnValue:false, errorText:"PalmSystem Not Available. Cordova is not installed?"});
 34 					}
 35 				}
 36 		};
 37 	}
 38 	
 39 	function isValidFileURI(uri){
 40 		if(uri){
 41 			// Length of URI should be less than 256
 42 			if(uri.length > 256){
 43 				log("URI IS TOO LONG!!!!!!!! " + uri.length);				
 44 				return false;
 45 			}
 46 			else{
 47 				// Only acceptable characters for filename is Alphanumeric and -_.
 48 				var pathandhost = uri.substring(uri.indexOf("://") + "://".length);
 49 				var path = pathandhost.substring(pathandhost.indexOf("/"));
 50 				var regex = new RegExp(/^[a-zA-Z0-9-_\/\.]*$/g);
 51 				var ret = regex.exec(path);
 52 				if(ret){
 53 					log("GOOD URI!!!!!!!! " );				
 54 					return true;
 55 				}
 56 				else{
 57 					log("INVALID URI!!!!!!!! " + uri);				
 58 					return false;
 59 				}
 60 			}
 61 		}
 62 		else{
 63 			log("NO URI!!!!!!!! " + uri);				
 64 			return false;
 65 		}
 66 		
 67 	}
 68 	
 69 	
 70 	/**
 71 	 * storage interface
 72 	 */
 73 	var Storage = function () {
 74 	};
 75 
 76 	/**
 77 	 * @namespace Error
 78 	 */
 79 	Error.ERROR_CODE = {
 80 			/**
 81 			 * There was an error while doing a file IO.
 82 			 * @since 1.3
 83 			 * @constant
 84 			 */
 85 			IO_ERROR : "IO_ERROR",
 86 
 87 			/**
 88 			 * There was an error while accessing external storage devices.
 89 			 * @since 1.3
 90 			 * @constant
 91 			 */
 92 			DEVICE_ERROR : "DEVICE_ERROR",
 93 			
 94 			/**
 95 			 * The input parameter has error.
 96 			 * @since 1.3
 97 			 * @constant
 98 			 */
 99 			BAD_PARAMETER : "BAD_PARAMETER",
100 
101 			/**
102 			 * The remote server returned error.
103 			 * @since 1.3
104 			 * @constant
105 			 */
106 			SERVER_ERROR : "SERVER_ERROR",
107 
108 			/**
109 			 * The network has error connecting to the remote site.
110 			 * @since 1.3
111 			 * @constant
112 			 */
113 			NETWORK_ERROR : "NETWORK_ERROR",
114 
115 			/**
116 			 * The network has error connecting to the remote site.
117 			 * @since 1.3
118 			 * @constant
119 			 */
120 			NETWORK_ERROR : "NETWORK_ERROR",
121 			
122 			/**
123 			 * The signage monitor system had error while executing the command.
124 			 * @since 1.3
125 			 * @constant
126 			 */
127 			SYSTEM_ERROR : "SYSTEM_ERROR",
128 	};
129 
130 	
131 	
132 	
133 	
134 	/**
135 	 * <p>
136 	 * This section describes the SCAP URI to locate resources for the SCAP strorage APIs.
137 	 * SCAP URI follows the syntax of a standard URI. 	  
138 	 * </p>
139 	 * <p>
140 	 * Those restrictions are applied to the SCAP URI.
141 	 * <ul>
142 	 * <li> If the protocol for the URI is file://, then allowd charecter sets are [a-zA-Z0-9-._]</li>
143 	 * <li> URI cannot be longer than a 256 length string </li>
144 	 * </ul>
145 	 * </p>
146 	 * 
147 	 * Those are formats that are recognized by SCAP storage APIs.
148 	 * <p>
149 	 * <div align=left>
150 	 * <table class="hcap_spec" width=400>
151 	 *   <thead><tr><th>Name</th><th>Description</th></tr></thead>
152 	 *   <tbody>
153 	 *       <tr>
154 	 *       	<th>file://internal/</th>
155 	 *       	<th>
156 	 *       	Locate to a file in internal memory space. No directories or files should be included in the path beyond root path.<br>
157 	 * 		 	If the path to the file destination is not found, directories for the file path will be automatically created.<br>
158 	 * 		 	Maximum length for a pathname is 255.	
159 	 *       	<p>(note: ../ is not allowed in the file path. '*' and '?' are also not supported.)</p>
160 	 *       	</th>
161 	 *       </tr>
162 	 *       <tr class="odd">
163 	 *       	<th>file://usb:[index]/</th>
164 	 *       	<th>
165 	 *       	Locate to a file in USB storage device at USB port:[index]. A USB storage device should be connected to the port.<br>
166 	 *       	If the path to the file destination is not found, directories for the file path will be automatically created.<br>
167 	 * 		 	Maximum length for a pathname is 255.	
168 	 *       	<p>(note: ../ is not allowed in the file path. '*' and '?' are also not supported.)</p> 
169 	 *       	</th>
170 	 *       </tr>
171 	 *       <tr>
172 	 *       	<th>file://sdcard:[index]/</th>
173 	 *       	<th>
174 	 *       	Locate to a file in SD card device at SD card port:[index]. A SD card storage device should be connected to the port.<br>
175 	 *       	If the path to the file destination is not found, directories for the file path will be automatically created.<br>
176 	 * 		 	Maximum length for a pathname is 255.	
177 	 *       	<p>(note: ../ is not allowed in the file path. '*' and '?' are also not supported.)</p> 
178 	 *       	</th>
179 	 *       </tr>
180 	 *       <tr  class="odd">
181 	 *       	<th>http://, https://</th>
182 	 *       	<th>
183 	 *       	Locate to a file in remote location. The file is downloaded using HTTP GET protocol. 
184 	 *       	Secure connection using https protocol is also supported.
185 	 *       	</th>
186 	 *       </tr>
187 	 *       <tr>
188 	 *       	<th>
189 	 *       	ftp:// (FTP)<br>
190 	 *       	sftp:// (FTP with SSH file transfer protocol)<br>
191 	 *       	ftps:// (FTP over SSL/TLS)<br>
192 	 *       	</th>
193 	 *       	<th>
194 	 *       	Locate to a file from FTP server. sftp (FTP with SSH file transfer) and ftps (FTP with SSL/TLS) is also supported.</br>
195 	 *       	Additional security option may be defined for sftp and ftps.</br>
196 	 *       	User name, password should be part of the URI if needed. </br>
197 	 *       	ex) ftp://user:password@my.ftp.site:21/path/to/file.txt
198 	 *       	If port number is not defined in URI, port number will be 21 (ftp or ftps) or 22 (sftp). </br>
199 	 *       	If auth is not defined in URI, 'anonymous:anonymous@' will be used if protocol is ftp/ftps. </br>
200 	 *       	</th>
201 	 *       </tr>
202 	 *   </tbody>
203 	 * </table>
204 	 * </div>
205 	 * </p>
206 	 * 
207 	 * Note : Copied files can be accessed by local/USB application from the "./content" directory of the local/USB application</br>
208 	 * Note : Copied files can be accessed from local http file server.(http://127.0.0.1:9080/[copied_filename]) </br>
209 	 * Note : Files that are copied to USB storage can be accessed from the local http file server.(http://127.0.0.1:9080/external/usb/[usb_port]) </br>
210 	 * TIP : If DNS server is not set in the monitor, accessing local file server using 'localhost' can take a long time to load the resource.
211 	 * Use '127.0.0.1' instead.
212 	 * 
213 	 * @namespace Storage.SCAP_URI
214 	 * @typedef string
215 	 */
216 	Storage.SCAP_URI = "";
217 	
218 	/**
219 	 * Maximum buffer length for readFile/writeFile (10K)
220 	 * @constant
221 	 */
222 	Storage.MAX_BUFFER_LENGTH = 1024 * 10;
223 
224 	/**
225 	 * @namespace Storage.AppMode
226 	 */
227 	Storage.AppMode = {
228 			/**
229 			 * USB
230 			 * @since 1.1
231 			 * @constant
232 			 */
233 			USB : "usb",
234 			/**
235 			 * local
236 			 * @since 1.1
237 			 * @constant
238 			 */
239 			LOCAL : "local"
240 	};
241 	
242 	/**
243 	 * <p>
244 	 * Downloads firmware from remote server using 'http' or 'https' protocol. 
245 	 * Before downloading, check the free storage size of the platform using Storage.getStorageInfo(). <br>
246 	 * Received firmware file will be deleted after upgrade is completed by calling Storage.upgradeFirmware(), which in turn results in monitor reboot. <br> 
247 	 * After reboot, stored firmware file will be deleted even if Storage.upgradeFirmware() was not called, so if wrong firmware file was downloaded, 
248 	 * just reboot the monitor without calling Storage.upgradeFirmware() to delete it.
249 	 * </p>
250 	 * 
251 	 * @example
252 	 * 
253 	 * function downloadFirmware() {
254 	 *    var successCb = function () { 
255 	 *      console.log("Download firmware is successful"); 
256 	 *    };
257 	 * 
258 	 *    var failureCb = function(cbObject) { 
259 	 *      var errorCode = cbObject.errorCode;
260 	 *      var errorText = cbObject.errorText; 
261 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
262 	 *    };
263 	 * 
264 	 *    var options = {
265 	 *       uri : "http://example.org/firmware.10-01.00.10_usb_V3_SECURED.epk"
266 	 *    };
267 	 *    
268 	 *    var storage = new Storage(); 
269 	 *    storage.downloadFirmware(successCb, failureCb, options);
270 	 *    
271 	 * }
272 	 * 
273 	 * 
274 	 * @class storage
275 	 * @param {Function}
276 	 *            successCallback success callback function.
277 	 * @param {Function}
278 	 *            errorCallback failure callback function.
279 	 * @param {Object} options
280 	 * <div align=left>
281 	 * <table class="hcap_spec" width=400>
282 	 *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
283 	 *   <tbody>
284 	 *       <tr><th>uri</th><th>String</th><th>URI for the firmware(in http or https)</a></th><th>required</th></tr>
285 	 *   </tbody>
286 	 * </table>
287 	 * </div>
288 	 * @returns
289 	 *            <p>
290 	 *            After the method is successfully executed, successCallback is called without any parameter.</br>
291 	 *            If an error occurs, errorCallback is called with errorCode and errorText as parameters.
292 	 *            </p>
293 	 * @since 1.2
294 	 * @see
295 	 * <a href="Storage%23upgradeFirmware.html">Storage.upgradeFirmware()</a>, 
296 	 * <a href="Storage%23getFirmwareUpgradeStatus.html">Storage.getFirmwareUpgradeStatus()</a><br>
297 	 */
298 	Storage.prototype.downloadFirmware = function (successCallback, errorCallback, options) {
299 
300 		service.Request("luna://com.webos.service.commercial.signage.storageservice", {
301 			method : "downloadFirmware",
302 			parameters : {
303 				uri : options.uri
304 			},
305 			onSuccess : function(result) {
306 				if(result.returnValue === true){
307 					successCallback();
308 				}
309 				else{
310 					errorCallback({errorCode:result.errorCode, errorText:result.errorText});
311 				}
312 			},
313 			onFailure : function(result) {
314 				errorCallback({errorCode:result.errorCode, errorText:result.errorText});
315 			}
316 		});
317 	};
318 
319 	/**
320 	 * <p>
321 	 * Upgrades firmware using stored file which was downloaded by calling Storage.downloadFirmware(). 
322 	 * If upgrade is successful, the monitor will restart automatically. 
323 	 * 
324 	 * </p>
325 	 * 
326 	 * @example
327 	 * 
328 	 * function upgradeFirmware() {
329 	 *    var successCb = function () { 
330 	 *      console.log("firmware upgrade is successful"); 
331 	 *    };
332 	 * 
333 	 *    var failureCb = function(cbObject) { 
334 	 *      var errorCode = cbObject.errorCode;
335 	 *      var errorText = cbObject.errorText; 
336 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
337 	 *    };
338 	 * 
339 	 *    var storage = new Storage(); 
340 	 *    storage.upgradeFirmware(successCb, failureCb);
341 	 * }
342 	 * 
343 	 * @class storage
344 	 * @param {Function}
345 	 *            successCallback success callback function.
346 	 * @param {Function}
347 	 *            errorCallback failure callback function.
348 	 * @returns
349 	 *            <p>
350 	 *            After the method is successfully executed, successCallback is called without any parameter.</br>
351 	 *            If an error occurs, errorCallback is called with errorCode and errorText as parameters.
352 	 *            </p>
353 	 * @since 1.2
354 	 * @see
355 	 * <a href="Storage%23downloadFirmware.html">Storage.downloadFirmware()</a>, <a href="Storage%23getFirmwareUpgradeStatus.html">Storage.getFirmwareUpgradeStatus()</a><br>
356 	 */
357 	Storage.prototype.upgradeFirmware = function (successCallback, errorCallback) {
358 
359 		service.Request("luna://com.webos.service.commercial.signage.storageservice", {
360 			method : "upgradeFirmware",
361 			parameters : {},
362 			onSuccess : function(result) {
363 				if(result.returnValue === true){
364 					successCallback();
365 				}
366 				else{
367 					errorCallback({errorCode:result.errorCode, errorText:result.errorText});
368 				}
369 			},
370 			onFailure : function(result) {
371 				errorCallback({errorCode:result.errorCode, errorText:result.errorText});
372 			}
373 		});
374 	};
375 
376 	/**
377 	 * <p>
378 	 * Gets the status of firmware upgrading. 
379 	 * 
380 	 * </p>
381 	 * 
382 	 * @example
383 	 * 
384 	 * function getFirmwareUpgradeStatus() {
385 	 *    var successCb = function (cbObject) { 
386 	 *      console.log("status " + cbObject.status);
387 	 *      console.log("upgradeProgress " + cbObject.upgradeProgress); 
388 	 *      console.log("downloadProgress " + cbObject.downloadProgress);
389 	 *    };
390 	 * 
391 	 *    var failureCb = function(cbObject) { 
392 	 *      var errorCode = cbObject.errorCode;
393 	 *      var errorText = cbObject.errorText; 
394 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
395 	 *    };
396 	 * 
397 	 *    var storage = new Storage(); 
398 	 *    storage.getFirmwareUpgradeStatus(successCb, failureCb);
399 	 * 
400 	 * }
401 	 * 
402 	 * @class storage
403 	 * @param {Function}
404 	 *            successCallback success callback function.
405 	 * @param {Function}
406 	 *            errorCallback failure callback function.
407 	 * @return {Object} 
408 	 * <div align=left>
409 	 * <table class="hcap_spec" width=400>
410 	 *   <thead><tr><th>Property</th><th>Type</th><th>Description</th></tr></thead>
411 	 *   <tbody>
412      *       <tr><th>status</th><th>String</th><th>idle | downloading | ready | in progress | completed | fail</a></th></tr>
413      *       <tr class="odd"><th>downloadProgress</th><th>Number</th><th> 0 ~ 100 </a></th></tr>
414      *       <th>upgradeProgress</th><th>Number</th><th> 0 ~ 100 </a></th></tr>
415 	 *   </tbody>
416 	 * </table>
417 	 * </div>
418 	 * @since 1.2
419 	 * @see
420 	 * <a href="Storage%23downloadFirmware.html">Storage.downloadFirmware()</a>, 
421 	 * <a href="Storage%23upgradeFirmware.html">Storage.upgradeFirmware()</a></br>
422 	 */
423 	Storage.prototype.getFirmwareUpgradeStatus = function (successCallback, errorCallback) {
424 
425 		service.Request("luna://com.webos.service.commercial.signage.storageservice", {
426 			method : "getFirmwareUpgradeStatus",
427 			parameters : {},
428 			onSuccess : function(result) {
429 				if(result.returnValue === true){
430 					successCallback({status : result.status, upgradeProgress : result.upgradeProgress, downloadProgress : result.downloadProgress});
431 				}
432 				else{
433 					errorCallback({errorCode:result.errorCode, errorText:result.errorText});
434 				}
435 			},
436 			onFailure : function(result) {
437 				errorCallback({errorCode:result.errorCode, errorText:result.errorText});
438 			}
439 		});
440 	};
441 
442 	/**
443 	 * <p>
444 	 * Changes monitor logo image. Image can be loaded from internal|USB memory, or retrieved from remote server using 'http' or 'https'.
445 	 * Logo image has following restrictions :  <br>
446 	 *  - format : JPG or BMP <br>
447 	 *  - max resolution : 1920x1080 <br>
448 	 *  - max file size : 8 Mbytes for BMP <br>
449 	 * </p>
450 	 * 
451 	 * @example
452 	 * 
453 	 * function changeLogoImage() {
454 	 *    var successCb = function () { 
455 	 *      console.log("Upgrading logo image is successful"); 
456 	 *    };
457 	 * 
458 	 *    var failureCb = function(cbObject) { 
459 	 *      var errorCode = cbObject.errorCode;
460 	 *      var errorText = cbObject.errorText; 
461 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
462 	 *    };
463 	 * 
464 	 *    var options = {
465 	 *       uri : "http://example.org/myImage.jpg"
466 	 *    };
467 	 * 
468 	 *    var storage = new Storage(); 
469 	 *    storage.changeLogoImage(successCb, failureCb, options);
470 	 * 
471 	 * }
472 	 * 
473 	 * @class storage
474 	 * @param {Function}
475 	 *            successCallback success callback function.
476 	 * @param {Function}
477 	 *            errorCallback failure callback function.
478 	 * @param {Object} options
479 	 * <div align=left>
480 	 * <table class="hcap_spec" width=400>
481 	 *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
482 	 *   <tbody>
483 	 *       <tr><th>uri</th><th>String</th><th>URI for the logo image(http, https, file://internal or file://usb:[index])</a></th><th>required</th></tr>
484 	 *   </tbody>
485 	 * </table>
486 	 * </div>
487 	 * @returns
488 	 *            <p>
489 	 *            After the method is successfully executed, successCallback is called without any parameter.</br>
490 	 *            If an error occurs, errorCallback is called with errorCode and errorText as parameters.
491 	 *            </p>
492 	 * @since 1.2
493 	 * @see
494 	 * <a href="Storage%23upgradeFirmware.html">Storage.upgradeFirmware()</a><br>
495 	 */
496 	Storage.prototype.changeLogoImage = function (successCallback, errorCallback, options) {
497 
498 		service.Request("luna://com.webos.service.commercial.signage.storageservice", {
499 			method : "changeLogoImage",
500 			parameters : {
501 				uri : options.uri
502 			},
503 			onSuccess : function(result) {
504 				if(result.returnValue === true){
505 					successCallback();
506 				}
507 				else{
508 					errorCallback({errorCode:result.errorCode, errorText:result.errorText});
509 				}
510 			},
511 			onFailure : function(result) {
512 				errorCallback({errorCode:result.errorCode, errorText:result.errorText});
513 			}
514 		});
515 	};
516 
517 	/**
518 	 * <p>
519 	 * Upgrades application stored in local or USB using the one from remote server. 
520 	 * Remote server information(serverIP and serverPort) is set in display menu.<br>
521 	 * New application will be launched at next boot time and old application will be deleted at the same time. 
522 	 * Application on the server should be at <br> 
523 	 * "http://serverIP:serverPort/procentric/scap/application/scap_app.zip".
524 	 * <br>
525 	 * Note : Size of scap_app.zip (zip file itself and extracted files) should not exceed free storage size of the platform.<br>
526 	 * When application is being upgraded, following files exist at the same time : <br>
527 	 *    - old application <br>
528 	 *    - downloaded scap_app.zip <br> 
529 	 *    - content data stored by storage.copyFile() API and <br> 
530 	 *    - new application extracted from the downloaded scap_app.zip <br>
531 	 * So before upgrading the application, call storage.getStorageInfo() and check the free storage size. <br>
532 	 * <br>
533 	 * Note : Application should not include 'content' directory under application's root folder. <br>
534 	 * (It is reserved for Storage.copyFile() API.)
535 	 * 
536 	 * </p>
537 	 * 
538 	 * @example
539 	 * 
540 	 * function upgradeApplication() {
541 	 *    var successCb = function (cbObject) { 
542 	 *      console.log("Application Update successful"); 
543 	 *    };
544 	 * 
545 	 *    var failureCb = function(cbObject) { 
546 	 *      var errorCode = cbObject.errorCode;
547 	 *      var errorText = cbObject.errorText; console.log( " Error Code [" + errorCode + "]: " + errorText); 
548 	 *    };
549 	 * 
550 	 *    var options = {
551 	 *       to : Storage.AppMode.USB,
552 	 *       recovery : false
553 	 *    };   
554 	 *    
555 	 *    var storage = new Storage(); 
556 	 *    storage.upgradeApplication(successCb, failureCb, options);
557 	 * }
558 	 * 
559 	 * @class storage
560 	 * @param {Function}
561 	 *            successCallback success callback function.
562 	 * @param {Function}
563 	 *            errorCallback failure callback function.
564 	 * @param {Object} options
565 	 * <div align=left>
566 	 * <table class="hcap_spec" width=400>
567 	 *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
568 	 *   <tbody>
569 	 *       <tr><th>to</th><th>String</th><th><a href="Storage.AppMode.html#constructor">Storage.AppMode</a></th><th>required</th></tr>
570 	 *       <tr class="odd"><tr><th>recovery</th><th>Boolean</th><th>true : Recover old application if there was an error during upgrade. Default value.<br>
571 	 *       false : Remove old application to obtain free storage space.</a></th><th>optional</th></tr>
572 	 *       
573 	 *   </tbody>
574 	 * </table>
575 	 * </div>
576 	 * @returns
577 	 *            <p>
578 	 *            After the method is successfully executed, successCallback is called without any parameter.</br>
579 	 *            If an error occurs, errorCallback is called with errorCode and errorText.
580 	 *            </p>
581 	 * @since 1.0
582 	 * @since 1.1 options.to options.recovery added
583 	 * @see
584 	 * <a href="Storage%23removeApplication.html">Storage.removeApplication()</a><br>
585 	 */
586 	Storage.prototype.upgradeApplication = function (successCallback, errorCallback, options) {
587 
588 		service.Request("luna://com.webos.service.commercial.signage.storageservice", {
589 			method : "upgradeApplication",
590 			parameters : {
591 				from : 'remote',
592 				to : (options == undefined || options == null ? Storage.AppMode.LOCAL : options.to),
593 				recovery : (options == undefined || options == null ? false : options.recovery)
594 			},
595 			onSuccess : function(result) {
596 				if(result.returnValue === true){
597 					successCallback();
598 				}
599 				else{
600 					errorCallback({errorCode:result.errorCode, errorText:result.errorText});
601 				}
602 			},
603 			onFailure : function(result) {
604 				errorCallback({errorCode:result.errorCode, errorText:result.errorText});
605 			}
606 		});
607 
608 	};
609 
610 	/**
611 	 * <p>
612 	 * Removes application stored in local or USB storage.<br>
613 	 * 
614 	 * Current running application can't remove itself using this API.<br>
615 	 * (e.g. Application running from USB cannot remove itself using this API)
616 	 * 
617 	 * </p>
618 	 * 
619 	 * @example
620 	 * 
621 	 * function removeApplication() {
622 	 *    var successCb = function (cbObject) { 
623 	 *      console.log("Application removes successfully"); 
624 	 *    };
625 	 * 
626 	 *    var failureCb = function(cbObject) { 
627 	 *      var errorCode = cbObject.errorCode;
628 	 *      var errorText = cbObject.errorText; 
629 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
630 	 *    };
631 	 * 
632 	 *    var options = { 
633 	 *       to : Storage.AppMode.LOCAL
634 	 *    };   
635 	 *     
636 	 *    var storage = new Storage(); 
637 	 *    storage.removeApplication(successCb, failureCb, options);
638 	 * }
639 	 * 
640 	 * @class storage
641 	 * @param {Function}
642 	 *            successCallback success callback function.
643 	 * @param {Function}
644 	 *            errorCallback failure callback function.
645 	 * @param {Object} options
646 	 * <div align=left>
647 	 * <table class="hcap_spec" width=400>
648 	 *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
649 	 *   <tbody>
650 	 *       <tr><th>to</th><th>String</th><th><a href="Storage.AppMode.html#constructor">Storage.AppMode</a></th><th>required</th></tr>
651 	 *   </tbody>
652 	 * </table>
653 	 * </div>
654 	 * @returns
655 	 *            <p>
656 	 *            After the method is successfully executed, successCallback is called without any parameter.</br>
657 	 *            If an error occurs, errorCallback is called with errorCode and errorText.
658 	 *            </p>
659 	 * @since 1.1
660 	 * @see
661 	 * <a href="Storage%23upgradeApplication.html">Storage.upgradeApplication()</a><br>
662 	 */
663 
664 	Storage.prototype.removeApplication = function (successCallback, errorCallback, options) {
665 
666 		service.Request("luna://com.webos.service.commercial.signage.storageservice", {
667 			method : "removeApplication",
668 			parameters : {
669 				to : options.to
670 			},
671 			onSuccess : function(result) {
672 				if(result.returnValue === true) {
673 					successCallback();
674 				} else {
675 					errorCallback({errorCode:result.errorCode, errorText:result.errorText});
676 				}
677 			},
678 			onFailure : function(result) {
679 				errorCallback({errorCode:result.errorCode, errorText:result.errorText});
680 			}
681 		});
682 	};
683 
684 
685 	/**
686 	 * <p>
687 	 * Copies file.
688 	 * File can be copied from internal, external memory, or remote site to internal, external memory, or a remote FTP site.</br>
689 	 * </p>
690 	 * 
691 	 * @example 
692 	 * 
693 	 * function copyFile() {
694 	 *    var successCb = function (){
695 	 *      console.log("Copying File done.");
696 	 *    };
697 	 * 
698 	 *    var failureCb = function(cbObject){ 
699 	 *      var errorCode = cbObject.errorCode;
700 	 *      var errorText = cbObject.errorText; 
701 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
702 	 *    };
703 	 * 
704 	 *    // Copy local file in internal memory to another location in internal memory.
705 	 *    var options_local_to_local = { 
706 	 *      source: 'file://internal/copy_me.txt',
707 	 *      destination : 'file://internal/copy/to/here.txt'
708 	 *    };
709 	 * 
710 	 *    var storage = new Storage();
711 	 *    storage.copyFile(successCb, failureCb, options_local_to_local);
712 	 * 
713 	 *    // Copy remote file to internal memory.
714 	 *    // Then set the file as he source for an image tag.
715 	 *    var options_remote_to_local = { 
716 	 *      source : 'http://remote.file.site/copy_me.txt',
717 	 *      destination : 'file://internal/copy/to/here.txt'
718 	 *    }; 
719 	 * 
720 	 *    storage.copyFile(successCb, failureCb, options_remote_to_local);
721 	 *          
722 	 *    // Copy file from USB memory at port 1 to internal memory.
723 	 *    var options_usb_to_local = { 
724 	 *      source : 'file://usb:1/from/copy_me.txt',
725 	 *      destination : 'file://internal/copy/to/here.txt'
726 	 *    };
727 	 * 
728 	 *    storage.copyFile(
729 	 *      function() {	// Success Call back. Set the copied file as image source.
730 	 *         var imgElement = document.getElementById('myImage');
731 	 *         imgElement.src = 'http://127.0.0.1:9080/copy/to/here.jpg';
732 	 *      },
733 	 *      failureCb, options_usb_to_local);
734 	 * 
735 	 *    // download remote file and copy to USB storage at port 1.
736 	 *    // Then set the file as he source for an image tag.
737 	 *    var options_remote_to_usb = { 
738 	 *      source : 'http://remote.file.site/copy_me.jpg',
739 	 *      destination : 'file://usb:1/copy/to/here.jpg'
740 	 *    };
741 	 * 
742 	 *    storage.copyFile(
743 	 *      function() {	// Success Call back. Set the copied file as image source.
744 	 *         var imgElement = document.getElementById('myImage');
745 	 *         imgElement.src = 'http://127.0.0.1:9080/external/usb/1/copy/to/here.jpg';
746 	 *      },
747 	 *      failureCb, options_remote_to_usb);
748 	 * 
749 	 * 
750 	 *    // Copy file from redirected server.
751 	 *    var options_redirect = { 
752 	 *      source : 'http://remote.site.that.will.redirect/copy_me.txt',
753 	 *      destination : 'file://usb:1/copy/to/here.txt',
754 	 *      maxRedirection: 5
755 	 *    };
756 	 * 
757 	 *    storage.copyFile(successCb, failureCb, options_redirect);
758 	 *    
759 	 *    // Copy file from ftp server.
760 	 *    var options_ftp = { 
761 	 *      source : 'ftp://user:password@remote.ftp.site/copy_me.txt',
762 	 *      destination : 'file://internal/copy/to/here.txt',
763 	 *    };
764 	 * 
765 	 *    storage.copyFile(successCb, failureCb, options_ftp);
766 	 *    
767 	 *    // Copy internal file to  ftp server.
768 	 *    var options_ftp2 = { 
769 	 *      source : 'file://internal/send/me/away.txt',
770 	 *      destination : 'ftp://user:password@remote.ftp.site/sent.txt',
771 	 *    };
772 	 * 
773 	 *    storage.copyFile(successCb, failureCb, options_ftp2);
774 	 * }
775 	 * 
776 	 * @class storage
777 	 * @param {Function}
778 	 *            successCallback success callback function.
779 	 * @param {Function}
780 	 *            errorCallback failure callback function.
781 	 * @param {Object} options
782      * <div align=left>
783      * <table class="hcap_spec" width=400>
784      *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
785      *   <tbody>
786      *       <tr><th>source</th><th>{@link Storage.SCAP_URI}</th><th>URI to the source file</a></th><th>required</th></tr>
787      *       <tr class="odd"><tr><th>destination</th><th>{@link Storage.SCAP_URI}</th><th>URI to the destination file. </a></th><th>required</th></tr>
788      *       <th>ftpOption</th><th>Object</th><th>FTP/SFTP options. Additional options for FTP setting.</th><th>optional</th></tr>
789      *       <tr class="odd"><tr><th>ftpOption.secureOptions</th><th>Object</th><th>secure FTP options</a></th><th>optional</th></tr>
790      *       <th>ftpOption.secureOptions.privateKey</th><th>String</th><th>Private key for either key-based or hostbased user authentication (OpenSSH format)</a></th><th>optional</th></tr>
791      *       <tr class="odd"><tr><th>ftpOption.secureOptions.passphrase</th><th>String</th><th>For an encrypted private key, this is the passphrase used to decrypt it</a></th><th>optional</th></tr>
792      *       <th>ftpOption.connTimeout</th><th>Number</th><th>How long (in milliseconds) to wait for the control connection to be established (default : 10000 ms)</a></th><th>optional</th></tr>
793      *       <tr class="odd"><tr><th>ftpOption.pasvTimeout</th><th>Number</th><th>How long (in milliseconds) to wait for a PASV data connection to be established (default : 10000 ms)</a></th><th>optional</th></tr>
794      *       <th>ftpOption.keepalive</th><th>Number</th><th>How often (in milliseconds) to send a 'dummy'(NOOP) command to keep the connection alive (default : 10000 ms)</a></th><th>optional</th></tr>       
795      *       <tr class="odd"><th>httpOption</th><th>Object</th><th>HTTP/HTTPS file copy options</th><th>optional</th></tr>
796      *       <th>httpOption.maxRedirection</th><th>Number</th><th>Maximum number of allowed redirections.</br> 
797      *       Default value is 0, which means no redirection is allowed.</br>Request will be redirected if the response code was 301,
798      *       302,303, or 307 and a valid location was found in the response header. </br> 
799      *       This option is ignored if the source file is not a remote file. Maximum number of redirection is 5.</th><th>optional</th></tr>       
800      *       <tr class="odd"><tr><th>httpOption.headers</th><th>Object</th>
801      *       <th>The [name : value] pairs that will be included in the HTTP request header, for remote file request. </br>
802      *       This header data will be cascaded during redirection. </br> 
803      *       Maximum size of header data that can be contained is 1KB. </br> 
804      *       </a></th><th>optional</th></tr>
805      *       <tr><th>httpOption.timeout</th><th>Number</th>
806      *       <th> Milliseconds before the underlying TCP connection times out. 0 is for no time out. Default value is 0.</br>
807      *       Note that if there is a server side timeout, copy file can timeout before the timeout value set by this option.
808      *       </th><th>optional</th></tr>
809      *   </tbody>
810      * </table>
811      * </div>
812      * 
813 	 * @returns
814 	 *            <p>
815 	 *            After the method is successfully executed, successCallback is called without any parameter.</br>
816 	 *            If an error occurs, errorCallback is called with errorCode and errorText. </br>
817 	 *            To see how error codes are defined, check {@link Error.ERROR_CODE}
818 	 *            </p>
819 	 * 
820 	 * @since 1.0 
821 	 * @since 1.1 access to local file from remote application
822 	 * @since 1.2 options.maxRedirection
823 	 * @since 1.3 options.ftpOption
824 	 * @since 1.3 options.maxRedirection moves to options.httpOption.maxRedirection
825 	 * @since 1.3 options.httpOption.headers
826 	 * @since 1.3 options.httpOption.timeout
827 	 */
828 	Storage.prototype.copyFile = function (successCallback , errorCallback, options ) {
829 
830 		log("Options: " + JSON.stringify(options, null , 3));
831 
832 		if(!(options && isValidFileURI(options.destination) && isValidFileURI(options.source))){
833 			log("Bad options URI NOT VALID" );
834 			errorCallback({errorCode:"BAD_PARAMETER", errorText:JSON.stringify(options, null, 3)});
835 			return;
836 		}
837 		if(options.maxRedirection && options.maxRedirection > 5){
838 			log("Bad options TOO MANY REDIRECTION" );
839 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"Redirect cannot be more that 5"});
840 			return;
841 		}
842 		if(options.headers && JSON.stringify(options.headers).length > 1024){
843 			log("header too long header too long" );
844 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"Header data cannot be bigger than 1K"});
845 			return;			
846 		}
847 
848 		if(typeof options.httpOption === 'undefined'){
849 			options.httpOption = {};
850 		}
851 		
852 		// For backward compatibility with older 
853 		if(options.maxRedirection || options.headers){
854 			if(options.maxRedirection && typeof options.httpOption.maxRedirection === 'undefined'){
855 				options.httpOption.maxRedirection = options.maxRedirection;
856 			}
857 			if(options.headers && typeof options.httpOption.headers === 'undefined'){
858 				options.httpOption.headers = options.headers;					
859 			}
860 		}
861 		
862 		console.log(options);
863 			
864 		service.Request("luna://com.webos.service.commercial.signage.storageservice", {
865 			method : "fs/copyFile",
866 			parameters : {
867 							dest : options.destination, 
868 							src:options.source,
869 							ftpOption:options.ftpOption,
870 							httpOption : options.httpOption
871 						},
872 			onSuccess : function(result) {
873 				if(result.returnValue === true){
874 					log("SUCCESS");
875 					successCallback();
876 				}
877 				else{
878 					log("Err: " + result.errorText);
879 					errorCallback({errorCode:result.errorCode, errorText:result.errorText});
880 				}
881 			},
882 			onFailure : function(result) {
883 				log("Err: " + result.errorText);
884 				errorCallback({errorCode:result.errorCode, errorText:result.errorText});
885 			}
886 		});
887 	};
888 
889 	/**
890 	 * <p>
891 	 * Removes file in internal or external storage.
892 	 * Target path is described in URI form. 
893 	 * </p>
894 	 * If the target path is a file, it will be removed.</br>
895 	 * If the target path is a directory, the directory will be removed.</br>
896 	 * If 'recursive' parameter is 'true', any file or directory in the target directory will be removed.</br>
897 	 * If 'recursive' parameter is 'false', operation will fail if there is any file in that directory.</br>
898 	 * <p>
899 	 * file://internal/external, file://usb:[index]/content are predefined directory for special use, and cannot be removed. 
900 	 * </p>
901 	 * 
902 	 * @example 
903 	 * 
904 	 * function removeFile() {
905 	 *    var successCb = function (){
906 	 *      console.log("Removing File done.");
907 	 *    }; 
908 	 * 
909 	 *    var failureCb = function(cbObject){ 
910 	 *      var errorCode = cbObject.errorCode;
911 	 *      var errorText = cbObject.errorText; 
912 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
913 	 *    };
914 	 * 
915 	 * 
916 	 *    //delete a file
917 	 *    var options = { 
918 	 *      file: 'file://internal/delete_me.txt',
919 	 *    }; 
920 	 * 
921 	 *    var storage = new Storage();
922 	 *    storage.removeFile(successCb, failureCb, options);
923 	 * 
924 	 *    //delete a directory and contents in it
925 	 *    var options = { 
926 	 *      file: 'file://internal/delete/this/directory/',
927 	 *      recursive : true
928 	 *    }; 
929 	 * 
930 	 *    storage.removeFile(successCb, failureCb, options);
931 	 * 
932 	 *    //delete a directory, only if it's empty
933 	 *    var options = { 
934 	 *      file: 'file://internal/empty/directory/',
935 	 *      recursive : false
936 	 *    }; 
937 	 * 
938 	 *    storage.removeFile(successCb, failureCb, options);
939 	 * }
940 	 * 
941 	 * @class storage
942 	 * @param {Function}
943 	 *            successCallback success callback function.
944 	 * @param {Function}
945 	 *            errorCallback failure callback function.
946      * @param {Object} options
947      * <div align=left>
948      * <table class="hcap_spec" width=400>
949      *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
950      *   <tbody>
951      *       <tr><th>file</th><th>{@link Storage.SCAP_URI}</th><th>URI to the file to delete</a></th><th>required</th></tr>
952      *       <tr class="odd"><tr><th>recursive</th><th>Boolean</th><th>only meaningful when removing a directory. Default value is 'false'.</br>
953      *           If true, the directory and all contents in it will be removed.</br>
954      *           If false, removing the directory will fail if it is not empty. 
955      *            </a></th><th>optional</th></tr>
956      *   </tbody>
957      * </table>
958      * </div>
959 	 * 
960 	 * @returns
961 	 *            <p>
962 	 *            After the method is successfully executed, successCallback is called without any parameter.</br>
963 	 *            If an error occurs, errorCallback is called with errorCode and errorText.
964 	 *            To see how error codes are defined, check {@link Error.ERROR_CODE}
965 	 *            </p>
966 	 * 
967 	 * @since 1.0 1.1 options.recursive
968 	 */
969 	Storage.prototype.removeFile = function (successCallback , errorCallback, options ) {
970 
971 		if(!(options && isValidFileURI(options.file))){
972 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.file is a mandatory parameter"});
973 			return;
974 		}
975 		var param = {
976 				file : options.file	
977 		}
978 		if(options.recursive === true){
979 			param['recursive'] = true;
980 		}
981 
982 		service.Request("luna://com.webos.service.commercial.signage.storageservice", {
983 			method : "fs/removeFile",
984 			parameters : param,
985 			onSuccess : function(result) {
986 
987 				log("onSuccess");
988 
989 				if(result.returnValue === true){
990 					successCallback();
991 				}
992 				else{
993 					errorCallback({errorCode:result.errorCode, errorText:result.errorText});
994 				}
995 			},
996 			onFailure : function(result) {
997 				log("onFailure");
998 				errorCallback({errorCode:result.errorCode, errorText:result.errorText});
999 			}
1000 		});
1001 	};
1002 
1003 	/**
1004 	 * <p>
1005 	 * Lists files in a directory stored in external or internal memory. 
1006 	 * Directory location is in URI format. 
1007 	 * Listing a directory beyond the application root path is not allowed.
1008 	 * </p>
1009 	 * 
1010 	 * @example 
1011 	 * 
1012 	 * function listFiles() {
1013 	 * 
1014 	 *    var successCb = function (cbObject){
1015 	 *      var files = cbObject.files;
1016 	 *      for(var i = 0 ; i < files.length; ++i){
1017 	 *         var fileInfo = files[i];	
1018 	 *         console.log("File Name: " + fileInfo.name);
1019 	 *         console.log("File Type: " + fileInfo.type);
1020 	 *         console.log("File Size: " + fileInfo.size);
1021 	 *      }
1022 	 *    }; 
1023 	 * 
1024 	 *    var failureCb = function(cbObject){ 
1025 	 *      var errorCode = cbObject.errorCode;
1026 	 *      var errorText = cbObject.errorText; 
1027 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
1028 	 *    };
1029 	 * 
1030 	 *    // List files in the internal memory
1031 	 *    var listOption = { 
1032 	 *      path: "file://internal/list/this/dir"
1033 	 *    }; 
1034 	 * 
1035 	 *    var storage = new Storage();
1036 	 *    storage.listFiles(successCb, failureCb, listOption);
1037 	 *          
1038 	 *    // List files in the mass storage device in USB port 1.
1039 	 *    var listOption = { 
1040 	 *      path: "file://usb:1/list/this/dir"
1041 	 *    }; 
1042 	 * 
1043 	 *    storage.listFiles(successCb, failureCb, listOption);
1044 	 * 
1045 	 * }
1046 	 * 
1047 	 * @class storage
1048 	 * @param {Function}
1049 	 *            successCallback success callback function.
1050 	 * @param {Function}
1051 	 *            errorCallback failure callback function.
1052 	 *            
1053      * @param {Object} options
1054      * <div align=left>
1055      * <table class="hcap_spec" width=400>
1056      *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
1057      *   <tbody>
1058      *       <tr><th>path</th><th>{@link Storage.SCAP_URI}</th><th>URI to the directory to look for.</a></th><th>required</th></tr>
1059      *   </tbody>
1060      * </table>
1061      * </div>
1062      * 
1063 	 * @returns
1064 	 *            <p>
1065 	 *            After the method is successfully executed, successCallback is called with total count and an array of file info, which contains a list of File Info Object.
1066 	 *            '.' and '..' will not be included in the list.
1067 	 * <div align=left>
1068 	 * <table class="hcap_spec" width=400>
1069 	 *   <thead><tr><th>Property</th><th>Type</th><th>Description</th></tr></thead>
1070 	 *   <tbody>
1071      *       <tr><th>totalCount</th><th>Number</th>
1072      *       <th>Number of items</th>
1073      *       </tr>
1074 	 *       <tr><th>files</th><th>Array</th>
1075 	 *       <th>List of files in the directory. File Info has following properties.</th>
1076 	 *       </tr>
1077      *      
1078 	 *       <tr><th>files.name</th><th>String</th>
1079 	 *       <th>Name of the file</th>
1080 	 *       </tr>
1081 	 *       
1082 	 *       <tr><th>files.type</th><th>String</th>
1083 	 *       <th>Type of the file</th>
1084 	 *       </tr>
1085 	 *       
1086 	 *       <tr><th>files.size</th><th>Number</th>
1087 	 *       <th>Size of the File</th>
1088 	 *       </tr>
1089 	 *       
1090 	 *	</tbody>
1091 	 * </table>
1092 	 * </div>
1093 	 *            </p>
1094 	 *            <p>
1095 	 *            If an error occurs, errorCallback is called with errorCode and errorText.
1096 	 *            To see how error codes are defined, check {@link Error.ERROR_CODE}
1097 	 *            </p>
1098 	 *            
1099 	 * @since 1.0
1100 	 * @since 1.1 list a directory
1101 	 */
1102 	Storage.prototype.listFiles = function (successCallback , errorCallback, options) {		
1103 		var param = {
1104 		};
1105 
1106 		if(options && options.path){
1107 			if(isValidFileURI(options.path)){
1108 				param['pathURI'] = options.path;				
1109 			}
1110 			else{
1111 				errorCallback({errorCode:"BAD_PARAMETER", errorText:"File URI is not valid."});		
1112 				return;
1113 			}			
1114 		}
1115 		else{
1116 			param['pathURI'] = "file://internal/";
1117 		}
1118 
1119 		service.Request("luna://com.webos.service.commercial.signage.storageservice/", {
1120 			method : "fs/listFiles",
1121 			parameters : param,
1122 			onSuccess : function(result) {
1123 				if(result.returnValue === true){					
1124 					var files = [];
1125 					for(var i=0;i<result.files.length;++i){
1126 						log(result.files[i]);
1127 						var fileinfo = {
1128 							name: result.files[i].name,
1129 							type: (result.files[i].type === 'folder') ? 'folder' : 'file' ,
1130 							size: result.files[i].size							
1131 						}
1132 						files.push(fileinfo);
1133 					}
1134 										
1135 					var cbObj = {
1136 							files:files,
1137 							totalCount:result.totalCount
1138 					};
1139 					successCallback(cbObj);
1140 				}
1141 				else{
1142 					errorCallback({errorCode:result.errorCode, errorText:result.errorText});
1143 				}
1144 			},
1145 			onFailure : function(result) {
1146 				errorCallback({errorCode:result.errorCode, errorText:result.errorText});
1147 			}
1148 		});
1149 	};
1150 
1151 	/**
1152 	 * <p>
1153 	 * Gets internal memory status.
1154 	 * Returns free space and total space, in kilobytes.
1155 	 * If any external storage device is connected, the storage info for that device will be returned as well.
1156 	 * </p>
1157 	 * 
1158 	 * @example 
1159 	 * 
1160 	 * function getStorageInfo() {
1161 	 *    var successCb = function (cbObject){
1162 	 *      var free = cbObject.free;
1163 	 *      var total = cbObject.total;
1164 	 *      var used = cbObject.used;
1165 	 *      var externals = cbObject.externalMemory;
1166 	 *  	   
1167 	 *      console.log( "Total: " + total + "kilobytes"); 
1168 	 *      console.log( "Free: " + free + "kilobytes");
1169 	 *      console.log( "Used: " + used + "kilobytes"); 
1170 	 *
1171 	 *      for(var uri in externals){
1172 	 *         var external = externals[uri];
1173 	 *         console.log("base uri: " + uri);		// ex) usb:1
1174 	 *         console.log("Free: " + external.free);
1175 	 *         console.log("Used: " + external.used);
1176 	 *         console.log("Total: " + external.total);
1177 	 *      }
1178 	 *    }; 
1179 	 * 
1180 	 *    var failureCb = function(cbObject){ 
1181 	 *      var errorCode = cbObject.errorCode;
1182 	 *      var errorText = cbObject.errorText; 
1183 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
1184 	 *    };
1185 	 * 
1186 	 *    var storage = new Storage();
1187 	 *    storage.getStorageInfo(successCb, failureCb);
1188 	 *          
1189 	 * }
1190 	 * 
1191 	 * @class storage
1192 	 * @param {Function}
1193 	 *            successCallback success callback function.
1194 	 * @param {Function}
1195 	 *            errorCallback failure callback function.
1196 	 * @returns
1197 	 *            <p>
1198 	 *            After the method is successfully executed, successCallback is called with free and total space.
1199 	 * <div align=left>
1200 	 * <table class="hcap_spec" width=400>
1201 	 *   <thead><tr><th>Property</th><th>Type</th><th>Description</th></tr></thead>
1202 	 *   <tbody>
1203 	 *       <tr><th>free</th><th>Number</th>
1204 	 *       <th>
1205 	 *       Free space in internal memory, in KB.
1206 	 *       </th>
1207 	 *       </tr>
1208 	 *       <tr><th>total</th><th>Number</th>
1209 	 *       <th>
1210 	 *       Total space in internal memory, in KB.
1211 	 *       </th>
1212 	 *       </tr>
1213 	 *       <tr><th>used</th><th>Number</th>
1214 	 *       <th>
1215 	 *       Used space in internal memory, in KB.
1216 	 *       </th>
1217 	 *       </tr>
1218 	 *       <tr><th>externalMemory</th><th>Array</th>
1219 	 *       <th>
1220 	 *       <p>
1221 	 *       List of external memory connected to the device (ex.usb:1). Optional.
1222 	 *       </p>
1223 	 *       <p>Each external memory item is a JSON object containing following fields. </p>
1224 	 *      <table align="center" class="hcap_spec" width=400>
1225 	 *   		<thead><tr><th>Property</th><th>Type</th><th>Description</th></tr></thead>
1226 	 *   	    <tbody>
1227 	 *   	 	<tr><th>free</th><th>Number</th><th>Free space in the external memory, in KB.</th></tr>
1228 	 *   	 	<tr><th>used</th><th>Number</th><th>Used space in the external memory, in KB.</th></tr>
1229 	 *   	 	<tr><th>total</th><th>Number</th><th>Total space in the external memory, in KB.</th></tr>
1230 	 *          </tbody>
1231 	 *      </table>
1232 	 *       </th>
1233 	 *       </tr>	 
1234 	 *    </tbody>
1235 	 * </table>
1236 	 * </div>
1237 	 *            </p>
1238 	 *            <p>
1239 	 *            If an error occurs, errorCallback is called with errorCode and errorText.
1240 	 *            To see how error codes are defined, check {@link Error.ERROR_CODE}
1241 	 *            </p>
1242 	 * 
1243 	 * @since 1.0
1244 	 * @since 1.1 USB storage information
1245 	 * @since 1.3 SDCard storage information
1246 	 */
1247 	Storage.prototype.getStorageInfo = function (successCallback , errorCallback ) {
1248 
1249 		service.Request("luna://com.webos.service.commercial.signage.storageservice", {
1250 			method : "fs/storageInfo",
1251 			parameters : {},
1252 			onSuccess : function(result) {
1253 				log("returned : " + JSON.stringify(result, null, 3));
1254 				if(result.returnValue === true){
1255 					log("returned : " + JSON.stringify(result, null, 3));
1256 					var cbObj = {
1257 							free : result.spaceInfo.freeSize,
1258 							total : result.spaceInfo.totalSize,
1259 							used : result.spaceInfo.usedSize,
1260 							externalMemory : result.externalStorage
1261 					};
1262 					successCallback(cbObj);
1263 				}
1264 				else{
1265 					errorCallback({errorCode:result.errorCode, errorText:result.errorText});
1266 				}
1267 			},
1268 			onFailure : function(result) {
1269 				errorCallback({errorCode:result.errorCode, errorText:result.errorText});
1270 			}
1271 		});
1272 	};
1273 
1274 	/**
1275 	 * <p>
1276 	 * Creates a directory.
1277 	 * The path should be described in URI format.
1278 	 * If the URI is for external memory, external storage device should be connected to the external memory port with proper permission.
1279 	 * The directory will be created recursively.
1280 	 * </p>
1281 	 * 
1282 	 * @example 
1283 	 * 
1284 	 * function mkdir() {
1285 	 *    var successCb = function (){
1286 	 *      console.log( "directory created successfully"); 
1287 	 *    }; 
1288 	 * 
1289 	 *    var failureCb = function(cbObject){ 
1290 	 *      var errorCode = cbObject.errorCode;
1291 	 *      var errorText = cbObject.errorText; 
1292 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
1293 	 *    };
1294 	 * 
1295 	 *    // The directory will be created recursively.
1296 	 *    var mkdirOption = { 
1297 	 *      path: "file://internal/create/this/directory"
1298 	 *    }; 
1299 	 * 
1300 	 *    var storage = new Storage();
1301 	 *    storage.mkdir(successCb, failureCb, mkdirOption);
1302 	 * 
1303 	 * }
1304 	 * 
1305 	 * @class storage
1306 	 * @param {Function}
1307 	 *            successCallback success callback function.
1308 	 * @param {Function}
1309 	 *            errorCallback failure callback function.
1310 	 *            
1311      * @param {Object} options
1312      * <div align=left>
1313      * <table class="hcap_spec" width=400>
1314      *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
1315      *   <tbody>
1316      *       <tr><th>path</th><th>{@link Storage.SCAP_URI}</th><th>URI to the directory to create. </a></th><th>required</th></tr>
1317      *   </tbody>
1318      * </table>
1319      * </div>
1320      * 
1321 	 * @returns
1322 	 *            <p>
1323 	 *            After the method is successfully executed, successCallback is called without any parameter.</br>
1324 	 *            If an error occurs, errorCallback is called with errorCode and errorText.
1325 	 *            To see how error codes are defined, check {@link Error.ERROR_CODE}
1326 	 *            </p>
1327 	 * 
1328 	 * @since 1.1
1329 	 */
1330 	Storage.prototype.mkdir = function (successCallback , errorCallback,options ) {
1331 		if(!(options && isValidFileURI(options.path))){
1332 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.path is a mandatory parameter"});
1333 			return;
1334 		}
1335 		var param = {
1336 				pathURI : options.path	
1337 		}
1338 
1339 		service.Request("luna://com.webos.service.commercial.signage.storageservice", {
1340 			method : "fs/mkdir",
1341 			parameters : param,
1342 			onSuccess : function(result) {
1343 
1344 				log("onSuccess");
1345 
1346 				if(result.returnValue === true){
1347 					successCallback();
1348 				}
1349 				else{
1350 					errorCallback({errorCode:result.errorCode, errorText:result.errorText});
1351 				}
1352 			},
1353 			onFailure : function(result) {
1354 				log("onFailure");
1355 				errorCallback({errorCode:result.errorCode, errorText:result.errorText});
1356 			}
1357 		});
1358 	};
1359 
1360 	/**
1361 	 * <p>
1362 	 * Checks if the given file exists or not.
1363 	 * The path should be in URI format.
1364 	 * If the URI is for external memory, external storage device must be connected to the external memory port with proper permission.
1365 	 * </p>
1366 	 * 
1367 	 * @example 
1368 	 * 
1369 	 * function exists() {
1370 	 *    var successCb = function (cbObject){
1371 	 *      var exists = cbObject.exists;
1372 	 *      console.log( "The file exists: " + exists); 
1373 	 *    }; 
1374 	 * 
1375 	 *    var failureCb = function(cbObject){ 
1376 	 *      var errorCode = cbObject.errorCode;
1377 	 *      var errorText = cbObject.errorText; 
1378 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
1379 	 *    };
1380 	 * 
1381 	 *    var existsOption = { 
1382 	 *      path: "file://internal/to/be/or/not/to/be"
1383 	 *    }; 
1384 	 * 
1385 	 *    var storage = new Storage();
1386 	 *    storage.exists(successCb, failureCb, existsOption);
1387 	 * 
1388 	 * }
1389 	 * 
1390 	 * @class storage
1391 	 * @param {Function}
1392 	 *            successCallback success callback function.
1393 	 * @param {Function}
1394 	 *            errorCallback failure callback function.
1395 	 *            
1396      * @param {Object} options
1397      * <div align=left>
1398      * <table class="hcap_spec" width=400>
1399      *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
1400      *   <tbody>
1401      *       <tr><th>path</th><th>{@link Storage.SCAP_URI}</th><th>URI to the resource (internal/usb/sdcard).</a></th><th>required</th></tr>
1402      *   </tbody>
1403      * </table>
1404      * </div>
1405      * 
1406 	 * @returns
1407 	 *            <p>
1408 	 *            After the method is successfully executed, successCallback is called with a boolean attribute 'exists', which is true if the file exists and false otherwise.</br>
1409 	 *            If an error occurs, errorCallback is called with errorCode and errorText.
1410 	 *            To see how error codes are defined, check {@link Error.ERROR_CODE}
1411 	 *            </p>
1412 	 * 
1413 	 * @since 1.1
1414 	 */
1415 	Storage.prototype.exists = function (successCallback , errorCallback,options ) {
1416 
1417 		if(!(options && isValidFileURI(options.path))){
1418 			log("BAD_PARAMETER" );
1419 
1420 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.path is a mandatory parameter"});
1421 			return;
1422 		}
1423 		var param = {
1424 				pathURI : options.path
1425 		}
1426 
1427 		service.Request("luna://com.webos.service.commercial.signage.storageservice", {
1428 			method : "fs/exists",
1429 			parameters : param,
1430 			onSuccess : function(result) {
1431 
1432 				log("onSuccess");
1433 
1434 				if(result.returnValue === true){
1435 					log("returned : " + JSON.stringify(result, null, 3));
1436 					var cbObj = {
1437 							exists : result.exists
1438 					};
1439 					successCallback(cbObj);					
1440 				}
1441 				else{
1442 					errorCallback({errorCode:result.errorCode, errorText:result.errorText});
1443 				}
1444 			},
1445 			onFailure : function(result) {
1446 				log("onFailure");
1447 				errorCallback({errorCode:result.errorCode, errorText:result.errorText});
1448 			}
1449 		});
1450 	};
1451 
1452 	/**
1453 	 * <p>
1454 	 * Reads from a file.<br>
1455 	 * It is designed to read a small data file from filesystem (not suited for a big data file).
1456 	 * </p>
1457 	 * <p>
1458 	 * Note : For reading a big chunk of data, it is recommended to use AJAX with local file.
1459 	 * </p>
1460 	 * @example
1461 	 * 
1462 	 * function readFile() {
1463 	 *    // This example will read a file as binary.
1464 	 *    
1465 	 *    var successCb = function (cbObject){
1466 	 *      // If file is read as binary, array of uint8 will be returned. 
1467 	 *      // Create an image element, and set the source as the binary data.
1468 	 *      
1469 	 *      var binary_data = cbObject.data;
1470 	 *      var data_base64 = bin_array_to_base64(binary_data);
1471 	 *      var ele = document.createElement('img');
1472 	 *      ele.src = "data:image/jpeg;base64, " + data_base64;
1473 	 *      document.body.appendChild(ele); 
1474 	 *    }; 
1475 	 * 
1476 	 *    var failureCb = function(cbObject){ 
1477 	 *      var errorCode = cbObject.errorCode;
1478 	 *      var errorText = cbObject.errorText; 
1479 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
1480 	 *    };
1481 	 * 
1482 	 *     // Read file from the start, read the whole file, and read as binary
1483 	 *    var options = { 
1484 	 *      path: "file://internal/image.jpg",
1485 	 *      position : 0,
1486 	 *      encoding: 'binary'
1487 	 *    }; 
1488 	 * 
1489 	 *    var storage = new Storage();
1490 	 *    storage.readFile(successCb, failureCb, options);
1491 	 * 
1492 	 * 
1493 	 *    // This example will read file as text.
1494 	 *    var successCb = function (cbObject){
1495 	 *      // If file is read as text, utf encoded string will be returned.
1496 	 *      // Create an image element, and set the source as the binary data.
1497 	 *   
1498 	 *      var data_text = cbObject.data;
1499 	 *      var ele = document.createElement('div');
1500 	 *      ele.innerHTML = "Text is read: " + data_text;
1501 	 *      document.body.appendChild(ele); 
1502 	 *    }; 
1503 	 * 
1504 	 *    var failureCb = function(cbObject){ 
1505 	 *      var errorCode = cbObject.errorCode;
1506 	 *      var errorText = cbObject.errorText; 
1507 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
1508 	 *    };
1509 	 * 
1510 	 *    // Read file from the start, read the whole file, and read as text.
1511 	 *    var options = { 
1512 	 *      path : "file://internal/text.txt",
1513 	 *      position : 0,
1514 	 *      encoding: 'utf8'
1515 	 *    }; 
1516 	 * 
1517 	 *    var storage = new Storage();
1518 	 *    storage.readFile(successCb, failureCb, options);
1519 	 * 
1520 	 * }
1521 	 *
1522 	 * @example 
1523 	 *  // This is a recommended way of reading a big chunk of data from file with JQuery Ajax.
1524 	 *  // Reading a data chunk bigger than 50MB is not recommended because it can lead to memory overflow (depends on system).
1525 	 *  function readFileAjax(){
1526 	 *  	$.ajax({
1527 	 *  		url: "http://127.0.0.1:9080/chunk.data"
1528 	 *  	})
1529 	 *  	.fail(function(err){
1530 	 *  		// Handle error.
1531 	 *  	})
1532 	 *  	.done(function(data){
1533 	 *  		// Handle the data.
1534 	 *  	});
1535 	 *  } 
1536 	 * 
1537 	 * @class storage
1538 	 * @param {Function}
1539 	 *            successCallback success callback function.
1540 	 * @param {Function}
1541 	 *            errorCallback failure callback function.
1542 	 *            
1543      * @param {Object} options
1544      * <div align=left>
1545      * <table class="hcap_spec" width=400>
1546      *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
1547      *   <tbody>
1548      *       <tr><th>path</th><th>{@link Storage.SCAP_URI}</th><th>URI to the resource (internal/usb/sdcard). </a></th><th>required</th></tr>
1549      *       <tr class="odd"><tr><th>position</th><th>Number</th><th>Position where this file will be read from. Default value is 0.</br> 
1550      *       If the value of the position parameter is out of the range of the input file, error will be returned.</a></th><th>optional</th></tr>
1551      *       <tr><th>length</th><th>Number</th><th>The length of the Read buffer. Maximum length of the buffer that can be read is currently 10KB. </br> 
1552      *            Default value is 10KB. </br>If the size of the file intended to be read is smaller than the length parameter, 
1553      *            return data will include the contents of the file.</a></th><th>optional</th></tr>
1554      *       <tr class="odd"><tr><th>encoding</th><th>String</th><th>Encoding method to be used for return value. </br>
1555      *            Default value is 'utf8'. Value of encoding can be:</br>
1556      *            'utf8' : Encoded as UTF-8. Return value will be a string.</br>
1557      *            'base64' : Encoded as base64. Return value will be a string.</br>
1558      *            'binary' : Raw binary data. Return value will be an ArrayBuffer.</br></a></th><th>optional</th></tr>
1559      *   </tbody>
1560      * </table>
1561      * </div>
1562 	 * @returns
1563 	 *            <p> 
1564 	 *            A string containing the file data with given encoding will be returned ('utf8', 'base64').</br>
1565 	 *            If the encoding is 'binary', an ArrayBuffer will be returned.</br>
1566 	 *            </p>
1567 	 *            <p>
1568 	 *            After the method is successfully executed, successCallback is called with file data.</br>
1569 	 *            If an error occurs, errorCallback is called with errorCode and errorText.
1570 	 *            To see how error codes are defined, check {@link Error.ERROR_CODE}
1571 	 *            </p>
1572 	 * 
1573 	 * @since 1.2
1574 	 */	
1575 	Storage.prototype.readFile = function (successCallback , errorCallback,options ){
1576 		if(!options){
1577 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.path is a mandatory parameter"});
1578 		}
1579 		else if(!isValidFileURI(options.path)){
1580 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.path is a mandatory parameter"});
1581 		}
1582 		else if(options.length && (options.length > Storage.MAX_BUFFER_LENGTH || options.length < 1 )){
1583 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"length should be > 0 and < " + Storage.MAX_BUFFER_LENGTH});			
1584 		}
1585 		else if(options.position && (options.position < 0 )){
1586 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"position should be > 0"});			
1587 		}		
1588 		else{
1589 			var params = {};
1590 
1591 			params.path = options.path,
1592 			params.length = options.length ? options.length : Storage.MAX_BUFFER_LENGTH;
1593 			params.position = options.position ? options.position : 0;
1594 			params.encoding = options.encoding ? options.encoding : 'utf-8';		
1595 
1596 			service.Request("luna://com.webos.service.commercial.signage.storageservice", {
1597 				method : "fs/readFile",
1598 				parameters : params,
1599 				onSuccess : function(result) {
1600 					if(result.returnValue){
1601 						if(params.encoding === 'binary'){
1602 							// Read as binary so return as ArrayBuffer.
1603 							// Returned data is a array of byte.
1604 							var byteArray = result.data;
1605 							var arrayView = new Uint8Array(byteArray.length);
1606 							for(var i=0;i<byteArray.length;++i){
1607 								arrayView[i]= byteArray[i];
1608 							}
1609 							successCallback({data:arrayView.buffer});								
1610 						}
1611 						else{
1612 							// return as a string
1613 							successCallback({data:result.data});								
1614 						}
1615 					}
1616 					else{
1617 						errorCallback({errorCode:result.errorCode, errorText:result.errorText});
1618 					}
1619 				},
1620 				onFailure : function(result) {
1621 					errorCallback({errorCode:result.errorCode, errorText:result.errorText});
1622 				}
1623 			});			
1624 		}
1625 	}
1626 
1627 	/**
1628 	 * 
1629 	 * Writes file
1630 	 * 
1631 	 * @example 
1632 	 *   
1633 	 * function writeFile() {
1634 	 *    // This example will write binary data to file.
1635 	 *   
1636 	 *    var successCb = function (cbObject){
1637 	 *      console.log( "Successfully writen " + cbObject.written + " bytes" ); 
1638 	 *    }; 
1639 	 * 
1640 	 *    var failureCb = function(cbObject){ 
1641 	 *      var errorCode = cbObject.errorCode;
1642 	 *      var errorText = cbObject.errorText; 
1643 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
1644 	 *    };
1645 	 * 
1646 	 * 
1647 	 *    //Read a file as binary with an ajax call.
1648 	 *    var oReq = new XMLHttpRequest();
1649 	 *    oReq.open("GET", '/my_file.data', true);
1650 	 *    oReq.responseType = "arraybuffer";
1651 	 *    oReq.onload = function (oEvent) {
1652 	 *       var arrayBuffer = oReq.response; // Note: not oReq.responseText
1653 	 * 
1654 	 *      if (arrayBuffer) {
1655 	 *         var uint8View =  new Int8Array(arrayBuffer);
1656 	 *         var array = [];
1657 	 *         for(var i=0;i < uint8View.length;++i) {
1658 	 *            array[i] = uint8View[i];
1659 	 *         }
1660 	 * 	
1661 	 *         // write data from the start, read the whole data, and write as binary
1662 	 *         var options = {
1663 	 *            data: array,
1664 	 *            path: 'file://internal/data.dat',
1665 	 *            position : 0,
1666 	 *            mode :'truncate',
1667 	 *            offset:0,
1668 	 *            length : array.length,
1669 	 *            encoding: 'binary'
1670 	 *         }; 
1671 	 * 
1672 	 *         var storage = new Storage();
1673 	 *         storage.writeFile(successCb, failureCb, options);
1674 	 *      }
1675 	 *    };
1676 	 * 
1677 	 *    oReq.send(null);
1678 	 *    // This example will write text data to a file.
1679 	 *   
1680 	 *    var successCb = function (cbObject){
1681 	 *      console.log( "Successfully writen " + cbObject.written + " bytes" ); 
1682 	 *    }; 
1683 	 * 
1684 	 *    var failureCb = function(cbObject) { 
1685 	 *      var errorCode = cbObject.errorCode;
1686 	 *      var errorText = cbObject.errorText; 
1687 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
1688 	 *    };
1689 	 * 
1690 	 *     // write Text data, use utf-8 encoding, write all text.
1691 	 *    var textData = "Hello SCAP!!!!!"; 
1692 	 *    var options = { 
1693 	 *      data: textData,
1694 	 *      path: 'file://internal/text.txt',
1695 	 *      position : 0,
1696 	 *      mode :'truncate',
1697 	 *      offset:0,
1698 	 *      length : textData.length,
1699 	 *      encoding: 'utf8'
1700 	 *    }; 
1701 	 *
1702 	 *    var storage = new Storage();
1703 	 *    storage.writeFile(successCb, failureCb, options);
1704 	 * 
1705 	 * }
1706 	 *          
1707 	 * @class storage
1708 	 * @param {Function}
1709 	 *            successCallback success callback function.
1710 	 * @param {Function}
1711 	 *            errorCallback failure callback function.
1712 	 *            
1713      * @param {Object} options
1714      * <div align=left>
1715      * <table class="hcap_spec" width=400>
1716      *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
1717      *   <tbody>
1718      *       <tr><th>path</th><th>{@link Storage.SCAP_URI}</th><th>URI to the resource (internal/usb/sdcard).</a></th><th>required</th></tr>
1719      *       <tr class="odd"><tr><th>data</th><th>ArrayBuffer|String</th><th>Data to write to the file. Data type should be ArrayBuffer if encoding is 'binary' or string otherwise.</a></th><th>required</th></tr>
1720      *       <tr><th>mode</th><th>String</th><th>Write mode. Default is 'truncate'.</br>
1721      *            'truncate' : Truncate the file and start writing on it. File will be created if it doesn't exist. </br>
1722      *            'append'   : Append to the file. File will be created if it doesn't exist. </br>
1723      *            'position' : Write from the position given by option.position. File must exist for this mode. </br> </a></th><th>optional</th></tr>
1724      *       <tr class="odd"><tr><th>position</th><th>Number</th><th>Position where this file will be written. Default value is 0. This option is valid only if mode is 'position'.</br> 
1725      *       If position is bigger than the existing file for positional write, the gap between the file contents and write position will be filled with '\00' character.</a></th><th>optional</th></tr>
1726      *       <tr><th>length</th><th>Number</th><th>Write buffer length in bytes. Maximum buffer size is 10KB. </br>Default value is data.length, 
1727      *       or 10KB if data.length-offset > 10KB.</a></th><th>optional</th></tr>
1728      *       <tr class="odd"><tr><th>encoding</th><th>String</th><th>Encoding to be applied to input data. Default value is 'utf8'.</br>
1729      *            'utf8' : input data is encoded as UTF-8. options.data should be a string.</br>
1730      *            'base64' : input data is encoded as base64. options.data should be a string.</br>
1731      *            'binary' : input data is encoded as raw binary. options.data should be an ArrayBuffer.</br></a></th><th>optional</th></tr>
1732      *       <tr><th>offset</th><th>Number</th><th>Offset from buffer. Default value is 0. If offset+length > data.length, error will be returned.</a></th><th>optional</th></tr>
1733      *   </tbody>
1734      * </table>
1735      * </div>
1736      * 
1737 	 * @returns
1738 	 *            <p>
1739 	 *            After the method is successfully executed, successCallback is called with the number of bytes written.</br>
1740 	 *            The number of bytes written may be more than the length of the actual data. </br>
1741 	 *            If an error occurs, errorCallback is called with errorCode and errorText.
1742 	 *            To see how error codes are defined, check {@link Error.ERROR_CODE}
1743 	 *            </p>
1744 	 * 
1745 	 * @since 1.2
1746 	 */		
1747 	Storage.prototype.writeFile = function (successCallback , errorCallback,options ){
1748 		if(!options){
1749 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.path is a mandatory parameter"});
1750 		}
1751 		else if(!isValidFileURI(options.path)){
1752 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.path is a is not valid"});
1753 		}
1754 		else if(!options.data){
1755 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.data is a mandatory parameter"});
1756 		}		
1757 		else if(options.mode && (options.mode !== 'truncate' && options.mode !== 'append' && options.mode !== 'position')){
1758 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"mode should be 'truncate'|'append'|'position'"});			
1759 		}
1760 		else if(options.position && (options.position < 0 )){
1761 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"position should be > 0"});			
1762 		}
1763 		else if(options.offset && (options.offset < 0 )){
1764 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"offset should be > 0"});			
1765 		}				
1766 		else if(options.length && (options.length > Storage.MAX_BUFFER_LENGTH || options.length < 1 )){
1767 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"length should be > 0 and < " + Storage.MAX_BUFFER_LENGTH});			
1768 		}
1769 		else if(options.encoding && (options.encoding !== 'utf8' && options.encoding !== 'binary' && options.encoding !== 'base64' )){
1770 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"Invalid encoding: " + options.encoding});			
1771 		}	
1772 		
1773 		else{
1774 			log("REQUEST!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1775 			var params = {};
1776 			params.path = options.path;
1777 			params.mode = options.mode ? options.mode : 'truncate';
1778 			params.position =  options.position ? options.position : 0;
1779 			params.encoding = options.encoding ? options.encoding : 'utf8';
1780 			var offset = options.offset ? options.offset : 0; 
1781 			// Input data is array Buffer when encoding is binary
1782 			if(params.encoding === 'binary'){
1783 				log("binary, size is: " + options.data.byteLength);		
1784 				var uint8View =  new Uint8Array(options.data);
1785 				log("uint8View: " + uint8View);
1786 				var maxLength = options.length ? options.length : Storage.MAX_BUFFER_LENGTH;
1787 				var array = [];
1788 				var count = 0;
1789 				for(var i=offset;i<uint8View.length && count < maxLength;++i, count++){
1790 					array[count] = uint8View[i];					
1791 				}
1792 				log("array length: " + count);
1793 				
1794 				params.data = array;
1795 				params.length = count;
1796 				params.offset =  0;
1797 			}
1798 			// input data is base64 encoded string if encoding is base64
1799 			else if(params.encoding === 'base64'){
1800 				var maxLength = options.length ? options.length : Storage.MAX_BUFFER_LENGTH;
1801 				log("base64, size is: " + options.data.length);		
1802 				var base64Str = options.data;
1803 				var decodedRaw = window.atob(base64Str);
1804 				var decoded = decodedRaw.substring(offset, offset+maxLength);
1805 				var arrayView = new Uint8Array(decoded.length);
1806 				  
1807 				for(i = 0; i < decoded.length; i++) {
1808 					arrayView[i] = decoded.charCodeAt(i);
1809 				}
1810 								
1811 				var array = [];
1812 				for(var i=0;i<arrayView.length;++i){
1813 					array[i] = arrayView[i];
1814 				}
1815 
1816 				params.data = array;
1817 				params.length = array.length;
1818 				params.offset =  0;
1819 			}			
1820 			// input data is utf-8 text. 
1821 			else{
1822 				var maxLength = options.length ? options.length : Storage.MAX_BUFFER_LENGTH;
1823 				//var endPosition = (options.offset + maxLength) > options.data.length ? options.data.length : (options.offset + maxLength);
1824 				params.data = options.data.substring(offset, offset + maxLength);
1825 				params.length = params.data.length;
1826 				params.offset =  0;
1827 			}			
1828 			try{
1829 				service.Request("luna://com.webos.service.commercial.signage.storageservice", {
1830 					method : "fs/writeFile",
1831 					parameters : params,
1832 					onSuccess : function(result) {
1833 						log("onSuccess!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1834 						if(result.returnValue){
1835 							successCallback({written:result.written});
1836 						}
1837 						else{
1838 							log("FAILED: " + result.errorText );
1839 							errorCallback({errorCode:result.errorCode, errorText:result.errorText});
1840 						}
1841 					},
1842 					onFailure : function(result) {
1843 						log("onFailure!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1844 						log("FAILED: " + result.errorText );					
1845 						errorCallback({errorCode:result.errorCode, errorText:result.errorText});
1846 					}
1847 				});	
1848 			} catch (err){
1849 				log("EXCEPTION!!!!!!!!!!!!!!!!!" + err);					
1850 			}
1851 		}
1852 	}	
1853 
1854 	/**
1855 	 * 
1856 	 * Gets file stat. Stat for linked file is not shown.
1857 	 * 
1858 	 * @example 
1859 	 * 
1860 	 * function statFile() {
1861 	 *    var successCb = function (cbObject){
1862 	 *      console.log( "Show File Stat: " ); 
1863 	 *      console.log( JSON.stringify(cbObject));
1864 	 *    }; 
1865 	 * 
1866 	 *    var failureCb = function(cbObject){ 
1867 	 *      var errorCode = cbObject.errorCode;
1868 	 *      var errorText = cbObject.errorText; 
1869 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
1870 	 *    };
1871 	 * 
1872 	 *    var options = { 
1873 	 *      path: 'file://internal/myFile.txt',
1874 	 *    }; 
1875 	 * 
1876 	 *    var storage = new Storage();
1877 	 *    storage.statFile(successCb, failureCb, options);
1878 	 * }
1879 	 * 
1880 	 * @class storage
1881 	 * @param {Function}
1882 	 *            successCallback success callback function.
1883 	 * @param {Function}
1884 	 *            errorCallback failure callback function.
1885 	 *            
1886      * @param {Object} options
1887      * <div align=left>
1888      * <table class="hcap_spec" width=400>
1889      *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
1890      *   <tbody>
1891      *       <tr><th>path</th><th>{@link Storage.SCAP_URI}</th><th>URI to the resource (internal/usb/sdcard).</a></th><th>required</th></tr>
1892      *   </tbody>
1893      * </table>
1894      * </div>
1895 	 * @returns
1896 	 *            <p>
1897 	 *            After the method is successfully executed, successCallback is called with the file stat.</br>
1898 	 *            Example: 
1899 	 *            {   
1900 	 *            	  type: file|directory|unknown,
1901 	 *                size: 527,
1902 	 *                atime: Mon, 10 Oct 2011 23:24:11 GMT,
1903 	 *                mtime: Mon, 10 Oct 2011 23:24:11 GMT,
1904 	 *                ctime: Mon, 10 Oct 2011 23:24:11 GMT
1905 	 *            }
1906 	 *            </br>
1907 	 *            If an error occurs, errorCallback is called with errorCode and errorText.
1908 	 *            To see how error codes are defined, check {@link Error.ERROR_CODE}
1909 	 *            </p>
1910 	 * 
1911 	 * @since 1.2
1912 	 */		
1913 	Storage.prototype.statFile = function (successCallback , errorCallback,options ){
1914 		if(!(options && isValidFileURI(options.path))){
1915 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.path is a mandatory parameter"});
1916 		}
1917 		else if(!options.path){
1918 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.path is a mandatory parameter"});
1919 		}else{
1920 			try{
1921 				service.Request("luna://com.webos.service.commercial.signage.storageservice", {
1922 					method : "fs/statFile",
1923 					parameters : {path: options.path},
1924 					onSuccess : function(result) {
1925 						log("onSuccess!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1926 
1927 						if(result.returnValue){
1928 							successCallback(result.stat);
1929 						}
1930 						else{
1931 							log("FAILED: " + result.errorText );
1932 							errorCallback({errorCode:result.errorCode, errorText:result.errorText});
1933 						}
1934 					},
1935 					onFailure : function(result) {
1936 						log("onFailure!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1937 						log("FAILED: " + result.errorText );					
1938 						errorCallback({errorCode:result.errorCode, errorText:result.errorText});
1939 					}
1940 				});	
1941 			} catch (err){
1942 				log("EXCEPTION!!!!!!!!!!!!!!!!!" + err);					
1943 			}			
1944 		}
1945 	}
1946 
1947 	/**
1948 	 * 
1949 	 * Removes all files in given file system.
1950 	 * 
1951 	 * @example 
1952 	 * 
1953 	 * function removeAll() {
1954 	 *    var successCb = function (cbObject){
1955 	 *      console.log( "Removed all files " ); 
1956 	 *    }; 
1957 	 * 
1958 	 *    var failureCb = function(cbObject){ 
1959 	 *      var errorCode = cbObject.errorCode;
1960 	 *      var errorText = cbObject.errorText; 
1961 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
1962 	 *    };
1963 	 *
1964 	 *    var options = { 
1965 	 *      device: 'internal' // This will remove all files in the internal memory space.
1966 	 *    }; 
1967 	 * 
1968 	 *    var storage = new Storage();
1969 	 *    storage.removeAll(successCb, failureCb, options);
1970 	 * }
1971 	 *          
1972 	 * @class storage
1973 	 * @param {Function}
1974 	 *            successCallback success callback function.
1975 	 * @param {Function}
1976 	 *            errorCallback failure callback function.
1977 	 *            
1978      * @param {Object} options
1979      * <div align=left>
1980      * <table class="hcap_spec" width=400>
1981      *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
1982      *   <tbody>
1983      *       <tr><th>device</th><th>String</th><th>device to remove all files from. (internal, usb:[index], sdcard:[index])</a></th><th>required</th></tr>
1984      *   </tbody>
1985      * </table>
1986      * </div>
1987 	 * @returns
1988 	 *            <p>
1989 	 *            After the method is successfully executed, successCallback is called without any parameter.</br>
1990 	 *            If an error occurs, errorCallback is called with errorCode and errorText.
1991 	 *            To see how error codes are defined, check {@link Error.ERROR_CODE}
1992 	 *            </p>
1993 	 * 
1994 	 * @since 1.2
1995 	 */		
1996 	Storage.prototype.removeAll = function (successCallback , errorCallback,options ){
1997 		if(!options){
1998 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.device is a mandatory parameter"});
1999 		}
2000 		else if(!options.device){
2001 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.device is a mandatory parameter"});
2002 		}else{
2003 			try{
2004 				service.Request("luna://com.webos.service.commercial.signage.storageservice", {
2005 					method : "fs/removeAll",
2006 					parameters : {device: options.device},
2007 					onSuccess : function(result) {
2008 						log("onSuccess!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
2009 
2010 						if(result.returnValue){
2011 							successCallback();
2012 						}
2013 						else{
2014 							log("FAILED: " + result.errorText );
2015 							errorCallback({errorCode:result.errorCode, errorText:result.errorText});
2016 						}
2017 					},
2018 					onFailure : function(result) {
2019 						log("onFailure!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
2020 						log("FAILED: " + result.errorText );					
2021 						errorCallback({errorCode:result.errorCode, errorText:result.errorText});
2022 					}
2023 				});	
2024 			} catch (err){
2025 				log("EXCEPTION!!!!!!!!!!!!!!!!!" + err);					
2026 			}			
2027 		}
2028 	}	
2029 
2030 	/**
2031 	 * 
2032 	 * Flushes modified files to filesystem.
2033 	 * 
2034 	 * @example 
2035 	 * 
2036 	 * function fsync() {
2037 	 *    // This example will copy a file to USB and sync it.
2038 	 * 
2039 	 *    var failureCb = function(cbObject){ 
2040 	 *      var errorCode = cbObject.errorCode;
2041 	 *      var errorText = cbObject.errorText; 
2042 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
2043 	 *    };
2044 	 * 
2045 	 *    var storage = new Storage();
2046 	 *    storage.copyFile(
2047 	 *      function(){  // Copy was success. fsync the file.
2048 	 *         storage.fsync(
2049 	 *            function(){
2050 	 *               console.log("File synched!!!!!!!!!!");
2051 	 *            },
2052 	 *            failureCb,
2053 	 *            {path : "file://usb:1/file.jpg"}
2054 	 *         );
2055 	 *      }, 
2056 	 *      failureCb, 
2057 	 *      {source:"file://internal/this.jpg", destination:"file://usb:1/file.jpg"}
2058 	 *    );
2059 	 * 
2060 	 *    // This example will sync whole file system.
2061 	 *    var failureCb = function(cbObject){ 
2062 	 *      var errorCode = cbObject.errorCode;
2063 	 *      var errorText = cbObject.errorText; 
2064 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
2065 	 *   };
2066 	 * 
2067 	 *    storage.copyFile(
2068 	 *      function(){  // Copy was success. fsync the device.
2069 	 *         storage.fsync(
2070 	 *            function(){
2071 	 *               console.log("File synched!!!!!!!!!!");
2072 	 *            },
2073 	 *            failureCb, // Failure Callback
2074 	 *            {} // Options
2075 	 *         );
2076 	 *      }, 
2077 	 *      failureCb, 	// Failure Callback
2078 	 *      {source:"file://internal/this.jpg", destination:"file://usb:1/file.jpg"} // Options
2079 	 *    );
2080 	 * 
2081 	 * }
2082 	 *          
2083 	 * @class storage
2084 	 * @param {Function}
2085 	 *            successCallback success callback function.
2086 	 * @param {Function}
2087 	 *            errorCallback failure callback function.
2088 	 *            
2089      * @param {Object} options
2090      * <div align=left>
2091      * <table class="hcap_spec" width=400>
2092      *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
2093      *   <tbody>
2094      *       <tr><th>path</th><th>{@link Storage.SCAP_URI}</th><th>URI to the resource (internal/usb/sdcard).</br>If this parameter is not provided, whole file system is synced using 'sync' linux command.</a></th><th>optional</th></tr>
2095      *   </tbody>
2096      * </table>
2097      * </div>
2098      * 
2099 	 * @returns
2100 	 *            <p>
2101 	 *            After the method is successfully executed, successCallback is called without any parameter.</br>
2102 	 *            If an error, errorCallback is called with errorCode and errorText.
2103 	 *            To see how error codes are defined, check {@link Error.ERROR_CODE}
2104 	 *            </p>
2105 	 * 
2106 	 * @since 1.2
2107 	 */		
2108 	Storage.prototype.fsync = function (successCallback , errorCallback,options ){
2109 		try{
2110 			var params = {};
2111 			if(options && options.path){
2112 				if(isValidFileURI(options.path)){
2113 					params.path =  options.path;					
2114 				}
2115 				else{
2116 					errorCallback({errorCode:"BAD_PARAMETER", errorText:"Invalid File URI"});
2117 					return;
2118 				}
2119 			}
2120 			
2121 			service.Request("luna://com.webos.service.commercial.signage.storageservice", {
2122 				method : "fs/fsyncFile",
2123 				parameters :params,
2124 				onSuccess : function(result) {
2125 					log("onSuccess!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
2126 					if(result.returnValue){
2127 						successCallback();
2128 					}
2129 					else{
2130 						log("FAILED: " + result.errorText );
2131 						errorCallback({errorCode:result.errorCode, errorText:result.errorText});
2132 					}
2133 				},
2134 				onFailure : function(result) {
2135 					log("onFailure!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
2136 					log("FAILED: " + result.errorText );					
2137 					errorCallback({errorCode:result.errorCode, errorText:result.errorText});
2138 				}
2139 			});	
2140 		} catch (err){
2141 			log("EXCEPTION!!!!!!!!!!!!!!!!!" + err);					
2142 		}			
2143 	}			
2144 
2145 	/**
2146 	 * 
2147 	 * Moves a file or directory.
2148 	 * If newPath already exists, it will be replaced. </br>
2149 	 * If newPath and oldPath refer to a same file, it will return success but do nothing. </br>
2150 	 * If oldPath is a directory, newPath must be either non-existing or emptry directory. </br>
2151 	 * 
2152 	 * <p>
2153 	 *  file://internal/external, file://usb:[usb_port]/content are predefined directory for special use, and cannot be moved. 
2154 	 * </p>
2155 	 * @example 
2156 	 * 
2157 	 * function moveFile() {
2158 	 *    var successCb = function (){
2159 	 *      console.log("Move File done.");
2160 	 *    }; 
2161 	 * 
2162 	 *    var failureCb = function(cbObject){ 
2163 	 *      var errorCode = cbObject.errorCode;
2164 	 *      var errorText = cbObject.errorText; 
2165 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
2166 	 *    };
2167 	 * 
2168 	 *    var options = { 
2169 	 *      oldPath: 'file://internal/org.txt',
2170 	 *      newPath : 'file://internal/new.txt'
2171 	 *    };
2172 	 * 
2173 	 *    var storage = new Storage();
2174 	 *    storage.moveFile(successCb, failureCb, options);
2175 	 * }
2176 	 * 
2177 	 * @class storage
2178 	 * @param {Function}
2179 	 *            successCallback success callback function.
2180 	 * @param {Function}
2181 	 *            errorCallback failure callback function.
2182 	 *            
2183      * @param {Object} options
2184      * <div align=left>
2185      * <table class="hcap_spec" width=400>
2186      *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
2187      *   <tbody>
2188      *       <tr><th>oldPath</th><th>{@link Storage.SCAP_URI}</th><th>URI to the original file (internal/usb/sdcard).</a></th><th>required</th></tr>
2189      *       <tr class="odd"><tr><th>newPath</th><th>{@link Storage.SCAP_URI}</th><th>URI to the new file (internal/usb/sdcard).</a></th><th>required</th></tr>
2190      *   </tbody>
2191      * </table>
2192      * </div>
2193 	 *            
2194 	 * @returns
2195 	 *            <p>
2196 	 *            After the method is successfully executed, successCallback is called without any parameter.</br>
2197 	 *            If an error occurs, errorCallback is called with errorCode and errorText.
2198 	 *            To see how error codes are defined, check {@link Error.ERROR_CODE}
2199 	 *            </p>
2200 	 * 
2201 	 * @since 1.2
2202 	 */		
2203 	Storage.prototype.moveFile = function (successCallback , errorCallback,options ){
2204 		if(!options){
2205 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.path is a mandatory parameter"});
2206 		}
2207 		else if(!isValidFileURI(options.oldPath)){
2208 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.oldpath is a mandatory parameter"});
2209 		}
2210 		else if(!isValidFileURI(options.newPath)){
2211 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.newPath is a mandatory parameter"});
2212 		}
2213 		else{
2214 			try{
2215 				service.Request("luna://com.webos.service.commercial.signage.storageservice", {
2216 					method : "fs/moveFile",
2217 					parameters : {oldPath: options.oldPath ,  newPath: options.newPath },
2218 					onSuccess : function(result) {
2219 						log("onSuccess!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
2220 
2221 						if(result.returnValue){
2222 							successCallback();
2223 						}
2224 						else{
2225 							log("FAILED: " + result.errorText );
2226 							errorCallback({errorCode:result.errorCode, errorText:result.errorText});
2227 						}
2228 					},
2229 					onFailure : function(result) {
2230 						log("onFailure!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
2231 						log("FAILED: " + result.errorText );					
2232 						errorCallback({errorCode:result.errorCode, errorText:result.errorText});
2233 					}
2234 				});	
2235 			} catch (err){
2236 				log("EXCEPTION!!!!!!!!!!!!!!!!!" + err);					
2237 			}			
2238 		}		
2239 	}
2240 
2241 	/**
2242 	 * 
2243 	 * Unzip file. It should be compressed in PKI-ZIP format.
2244 	 * 
2245 	 * @example 
2246 	 * function unzipFile() {
2247 	 *    var successCb = function (){
2248 	 *      console.log("Unzip File successful");
2249 	 *    }; 
2250 	 * 
2251 	 *    var failureCb = function(cbObject){ 
2252 	 *      var errorCode = cbObject.errorCode;
2253 	 *      var errorText = cbObject.errorText; 
2254 	 *      console.log( " Error Code [" + errorCode + "]: " + errorText); 
2255 	 *    };
2256 	 * 
2257 	 *    var options = { 
2258 	 *      zipPath: 'file://internal/myFile.zip',
2259 	 *      targetPath: 'file://internal/unzip/to/here',
2260 	 *    };
2261 	 * 
2262 	 *    var storage = new Storage();
2263 	 *    storage.unzipFile(successCb, failureCb, options);
2264 	 * }
2265 	 * 
2266 	 * @class storage
2267 	 * @param {Function}
2268 	 *            successCallback success callback function.
2269 	 * @param {Function}
2270 	 *            errorCallback failure callback function.
2271 	 *            
2272      * @param {Object} options
2273      * <div align=left>
2274      * <table class="hcap_spec" width=400>
2275      *   <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead>
2276      *   <tbody>
2277      *       <tr><th>zipPath</th><th>{@link Storage.SCAP_URI}</th><th>URI to the zip file (internal/usb/sdcard).</a></th><th>required</th></tr>
2278      *       <tr class="odd"><tr><th>targetPath</th><th>{@link Storage.SCAP_URI}</th><th>URI to the target directory where the contents of the zip file will be stored. (internal/usb/sdcard)</a></th><th>required</th></tr>
2279      *   </tbody>
2280      * </table>
2281      * </div>
2282      * 
2283 	 * @returns
2284 	 *            <p>
2285 	 *            After the method is successfully executed, successCallback is called without any parameter. </br>
2286 	 *            If an error occurs, errorCallback is called with errorCode and errorText.
2287 	 *            To see how error codes are defined, check {@link Error.ERROR_CODE}
2288 	 *            </p>
2289 	 * 
2290 	 * @since 1.2
2291 	 */		
2292 	Storage.prototype.unzipFile = function (successCallback , errorCallback,options ){
2293 		if(!options){
2294 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.path is a mandatory parameter"});
2295 		}
2296 		else if(!isValidFileURI(options.zipPath)){
2297 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.zipPath is a mandatory parameter"});
2298 		}
2299 		else if(!isValidFileURI(options.targetPath)){
2300 			errorCallback({errorCode:"BAD_PARAMETER", errorText:"options.targetPath is a mandatory parameter"});
2301 		}
2302 		else{
2303 			try{
2304 				service.Request("luna://com.webos.service.commercial.signage.storageservice", {
2305 					method : "fs/unzip",
2306 					parameters : {zipPath: options.zipPath ,  targetPath: options.targetPath },
2307 					onSuccess : function(result) {
2308 						log("onSuccess!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
2309 
2310 						if(result.returnValue){
2311 							successCallback();
2312 						}
2313 						else{
2314 							log("FAILED: " + result.errorText );
2315 							errorCallback({errorCode:result.errorCode, errorText:result.errorText});
2316 						}
2317 					},
2318 					onFailure : function(result) {
2319 						log("onFailure!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
2320 						log("FAILED: " + result.errorText );					
2321 						errorCallback({errorCode:result.errorCode, errorText:result.errorText});
2322 					}
2323 				});	
2324 			} catch (err){
2325 				log("EXCEPTION!!!!!!!!!!!!!!!!!" + err);					
2326 			}			
2327 		}	
2328 	}
2329 
2330 	module.exports = Storage;
2331 });
2332 
2333 Storage = cordova.require('cordova/plugin/storage'); // jshint ignore:line
2334