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