2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 var validator_ = xwalk.utils.validator;
18 var types_ = validator_.Types;
19 var native_ = new xwalk.utils.NativeManager(extension);
20 var privUtils_ = xwalk.utils;
22 function CommonFS() {};
24 CommonFS.cacheVirtualToReal = {};
25 CommonFS.isCacheReady = false;
26 CommonFS.listenerRegistered = false;
28 function clearCache() {
29 CommonFS.cacheVirtualToReal = {};
30 CommonFS.isCacheReady = false;
33 function _initializeCache() {
34 if (CommonFS.isCacheReady) {
37 var result = native_.callSync('Archive_fetchStorages', {});
39 if (native_.isFailure(result)) {
40 privUtils_.log("Exception while getting widget paths was thrown: " + native_.getErrorObject(result).message);
44 result = native_.getResultObject(result);
45 for (var i = 0; i < result.length; ++i) {
46 CommonFS.cacheVirtualToReal[result[i].name] = {
50 CommonFS.isCacheReady = true;
51 if (!CommonFS.listenerRegistered) {
53 tizen.filesystem.addStorageStateChangeListener(clearCache);
54 CommonFS.listenerRegistered = true;
56 privUtils_.log('Failed to register storage change listener, '
57 + 'storage information may be corrupted: ' + e.message);
64 CommonFS.toRealPath = function(aPath) {
65 var _fileRealPath = '', _uriPrefix = 'file://', i;
66 if (aPath.indexOf(_uriPrefix) === 0) {
67 _fileRealPath = aPath.substr(_uriPrefix.length);
68 } else if (aPath[0] != '/') {
71 var _pathTokens = aPath.split('/');
72 if (this.cacheVirtualToReal[_pathTokens[0]]
73 && (this.cacheVirtualToReal[_pathTokens[0]].state === undefined || this.cacheVirtualToReal[_pathTokens[0]].state === 'MOUNTED')) {
74 _fileRealPath = this.cacheVirtualToReal[_pathTokens[0]].path;
75 for (i = 1; i < _pathTokens.length; ++i) {
76 _fileRealPath += '/' + _pathTokens[i];
79 _fileRealPath = aPath;
82 _fileRealPath = aPath;
84 privUtils_.log("REAL PATH:" + _fileRealPath);
85 if (_fileRealPath === "undefined" || _fileRealPath === "null") {
86 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
91 CommonFS.isVirtualPath = function(aPath) {
92 var root = aPath.split("/")[0];
94 return this.cacheVirtualToReal[root] != undefined;
98 * Returns new unique opId
100 var getNextOpId = (function () {
102 incOpId = function () {
109 W: 1 << 0, // WRITABLE
110 E: 1 << 1, // ENUMERABLE
111 C: 1 << 2 // CONFIGURABLE
116 * function Messaging () {
117 * propertyFactory_(this, 'ids', [2,3,4], Property.W | Property.E | Property.C);
118 * propertyFactory_(this, 'name', 'Name', Property.E);
119 * propertyFactory_(this, 'age', 25, Property.W);
120 * propertyFactory_(this, 'something', 1);
121 * propertyFactory_(this, 'getSomething', Property.E, {get: function(){return 100;}});
124 * var m = new Messaging();
131 * m.name = 'A brand new name';
132 * privUtils_.log(m.name); // Name
134 function propertyFactory_(that, name, value, flags, options) {
136 if (options === null || typeof options !== 'object') {
139 if (!(options.get) && !(options.set)) {
140 options.value = value;
142 if ((flags & Property.W) != 0) { options.writable = true; }
143 if ((flags & Property.E) != 0) { options.enumerable = true; }
144 if ((flags & Property.C) != 0) { options.configurable = true; }
145 Object.defineProperty(
152 function checkMode(mode, access)
153 { if(access.indexOf(mode) == -1) {
154 throw new WebAPIException(WebAPIException.INVALID_ACCESS_ERR, 'Not allowed operation');
159 * Enumeration for the compression level.
162 var ArchiveCompressionLevel = {
169 var onprogressCallbacks = {};
170 var ARCHIVE_ONPROGRESS_CALLBACK = 'ArchiveOnprogressCallback';
172 var ArchiveFileProgressCallback = function(msg) {
173 if (native_.isFailure(msg)) {
177 var result = native_.getResultObject(msg);
178 if ('onprogress' === result.action && onprogressCallbacks.hasOwnProperty(result.opId)) {
179 onprogressCallbacks[result.opId](result.opId, result.value, result.filename);
183 native_.addListener(ARCHIVE_ONPROGRESS_CALLBACK, ArchiveFileProgressCallback);
186 * The ArchiveFileEntry interface provides access to ArchiveFile member information and file data.
187 * This constructor is for internal use only.
188 * It should be prohibited to call this constructor by user.
190 function ArchiveFileEntry(data, priv) {
191 if (!(this instanceof ArchiveFileEntry)) {
192 return new ArchiveFileEntry(data);
195 if (data === null || typeof data !== 'object') {
196 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
199 propertyFactory_(this, 'name', data.name || "", Property.E);
200 propertyFactory_(this, 'size', data.size || 0, Property.E);
201 propertyFactory_(this, 'compressedSize', data.compressedSize || 0, Property.E);
202 propertyFactory_(this, 'modified', new Date(data.modified * 1000) || null , Property.E);
204 function getHandle() {
207 else throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'Archive is not opened');
211 * Extracts ArchiveFileEntry to the given location.
213 this.extract = function () {
214 var args = validator_.validateArgs(arguments, [
215 { name: "destinationDirectory", type: types_.FILE_REFERENCE },
216 { name: "onsuccess", type: types_.FUNCTION, optional: true, nullable: true },
217 { name: "onerror", type: types_.FUNCTION, optional: true, nullable: true },
218 { name: "onprogress", type: types_.FUNCTION, optional: true, nullable: true },
219 { name: "stripName", type: types_.STRING, optional: true, nullable: true },
220 { name: "overwrite", type: types_.BOOLEAN, optional: true, nullable: true }
222 opId = getNextOpId();
224 if (!CommonFS.isVirtualPath(args.destinationDirectory)) {
225 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
226 "Destination directory should be virtual path or file.");
230 destinationDirectory : CommonFS.toRealPath(args.destinationDirectory),
231 stripName : args.stripName || null,
232 overwrite : args.overwrite || null,
234 handle : getHandle(),
238 var callback = function(result) {
239 if (native_.isFailure(result)) {
240 native_.callIfPossible(args.onerror, native_.getErrorObject(result));
242 var ret = native_.getResultObject(result);
243 delete onprogressCallbacks[opId];
244 native_.callIfPossible(args.onsuccess);
248 if (args.onprogress) {
249 onprogressCallbacks[opId] = args.onprogress;
252 var result = native_.call('ArchiveFileEntry_extract', callArgs, callback);
253 if (native_.isFailure(result)) {
254 throw native_.getErrorObject(result);
263 * The ArchiveManager interface provides methods for global operations related to ArchiveFile.
267 * ArchiveFile interface provides access to member files of the archive file.
268 * This constructor is for internal use only.
269 * It should be prohibited to call this constructor by user.
271 function ArchiveFile(data) {
272 if (!(this instanceof ArchiveFile)) {
273 return new ArchiveFile(data);
276 if (data === null || typeof data !== 'object') {
277 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
280 propertyFactory_(this, 'mode' , data.mode || "r", Property.E);
281 propertyFactory_(this, 'decompressedSize', data.decompressedSize || 0, Property.E);
283 var priv ={ handle: data.handle };
285 function getHandle() {
288 else throw new WebAPIException(WebAPIException.INVALID_STATE_ERR, 'ArchiveFile closed - operation not permitted');
292 * Adds a new member file to ArchiveFile.
294 this.add = function () {
295 var args = validator_.validateArgs(arguments, [
296 { name: "sourceFile", type: types_.FILE_REFERENCE },
297 { name: "onsuccess", type: types_.FUNCTION, optional: true, nullable: true },
298 { name: "onerror", type: types_.FUNCTION, optional: true, nullable: true },
299 { name: "onprogress", type: types_.FUNCTION, optional: true, nullable: true },
300 { name: "options", type: types_.DICTIONARY, optional: true, nullable: true }
302 opId = getNextOpId();
304 if (!CommonFS.isVirtualPath(args.sourceFile)) {
305 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
306 "sourceFile should be virtual path or file.");
309 var optionsAttributes = ["destination", "stripSourceDirectory", "compressionLevel"],
310 options = args.options || {};
312 for(var i in optionsAttributes) {
313 if (!options[optionsAttributes[i]]) {
314 options[optionsAttributes[i]] = null;
318 checkMode(this.mode, ["w","rw", "a"]);
321 sourceFile : CommonFS.toRealPath(args.sourceFile),
327 var callback = function(result) {
328 if (native_.isFailure(result)) {
329 native_.callIfPossible(args.onerror, native_.getErrorObject(result));
331 delete onprogressCallbacks[opId];
332 native_.callIfPossible(args.onsuccess);
336 if (args.onprogress) {
337 onprogressCallbacks[opId] = args.onprogress;
340 var result = native_.call('ArchiveFile_add', callArgs, callback);
341 if (native_.isFailure(result)) {
342 throw native_.getErrorObject(result);
349 * Extracts every file from this ArchiveFile to a given directory.
351 this.extractAll = function () {
352 var args = validator_.validateArgs(arguments, [
353 { name: "destinationDirectory", type: types_.FILE_REFERENCE },
354 { name: "onsuccess", type: types_.FUNCTION, optional: true, nullable: true },
355 { name: "onerror", type: types_.FUNCTION, optional: true, nullable: true },
356 { name: "onprogress", type: types_.FUNCTION, optional: true, nullable: true },
357 { name: "overwrite", type: types_.BOOLEAN, optional: true, nullable: true }
359 opId = getNextOpId();
361 if (!CommonFS.isVirtualPath(args.destinationDirectory)) {
362 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
363 "destinationDirectory should be virtual path or file.");
366 checkMode(this.mode, ["r","rw"]);
369 destinationDirectory : CommonFS.toRealPath(args.destinationDirectory),
370 overwrite : args.overwrite || null,
375 var callback = function(result) {
376 if (native_.isFailure(result)) {
377 native_.callIfPossible(args.onerror, native_.getErrorObject(result));
379 delete onprogressCallbacks[opId];
380 native_.callIfPossible(args.onsuccess);
384 if (args.onprogress) {
385 onprogressCallbacks[opId] = args.onprogress;
388 var result = native_.call('ArchiveFile_extractAll', callArgs, callback);
389 if (native_.isFailure(result)) {
390 throw native_.getErrorObject(result);
397 * Retrieves information about the member files in ArchiveFile.
399 this.getEntries = function () {
400 var args = validator_.validateArgs(arguments, [
401 { name: "onsuccess", type: types_.FUNCTION },
402 { name: "onerror", type: types_.FUNCTION, optional: true, nullable: true }
404 opId = getNextOpId();
406 checkMode(this.mode, ["r","rw"]);
413 var callback = function(result) {
414 if (native_.isFailure(result)) {
415 native_.callIfPossible(args.onerror, native_.getErrorObject(result));
418 var ret = native_.getResultObject(result);
419 ret.forEach(function (e) {
420 entries.push(new ArchiveFileEntry(e, priv));
422 args.onsuccess(entries);
426 var result = native_.call('ArchiveFile_getEntries', callArgs, callback);
427 if (native_.isFailure(result)) {
428 throw native_.getErrorObject(result);
435 * Retrieves information about ArchiveFileEntry with the specified name in ArchiveFile.
437 this.getEntryByName = function () {
438 var args = validator_.validateArgs(arguments, [
439 { name: "name", type: types_.STRING },
440 { name: "onsuccess", type: types_.FUNCTION },
441 { name: "onerror", type: types_.FUNCTION, optional: true, nullable: true }
443 opId = getNextOpId();
445 checkMode(this.mode, ["r","rw"]);
453 var callback = function(result) {
454 if (native_.isFailure(result)) {
455 native_.callIfPossible(args.onerror, native_.getErrorObject(result));
457 args.onsuccess(new ArchiveFileEntry(native_.getResultObject(result), priv));
461 var result = native_.call('ArchiveFile_getEntryByName', callArgs, callback);
462 if (native_.isFailure(result)) {
463 throw native_.getErrorObject(result);
470 * Closes the ArchiveFile.
472 this.close = function () {
473 var handle = priv.handle;
476 var result = native_.callSync('ArchiveFile_close', {'handle': handle});
478 if (native_.isFailure(result)) {
479 throw native_.getErrorObject(result);
486 var ArchiveManager = function () {
490 * Opens the archive file. After this operation, it is possible to add or get files to and from the archive.
492 ArchiveManager.prototype.open = function () {
493 var args = validator_.validateArgs(arguments, [
494 { name: "file", type: types_.FILE_REFERENCE },
495 { name: "mode", type: types_.ENUM, values: ["r", "rw", "w", "a"] },
496 { name: "onsuccess", type: types_.FUNCTION },
497 { name: "onerror", type: types_.FUNCTION, optional: true, nullable: true },
498 { name: "options", type: types_.DICTIONARY, optional: true, nullable: true }
500 opId = getNextOpId();
502 var optionsAttributes = ["overwrite"],
503 options = args.options || {};
505 for(var i in optionsAttributes) {
506 if (!options[optionsAttributes[i]]) {
507 options[optionsAttributes[i]] = null;
511 if (!CommonFS.isVirtualPath(args.file)) {
512 throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
513 "file should be virtual path or file.");
517 file : CommonFS.toRealPath(args.file),
524 var callback = function(result) {
525 if (native_.isFailure(result)) {
526 native_.callIfPossible(args.onerror, native_.getErrorObject(result));
528 args.onsuccess(new ArchiveFile(native_.getResultObject(result)));
532 var result = native_.call('ArchiveManager_open', callArgs, callback);
533 if (native_.isFailure(result)) {
534 throw native_.getErrorObject(result);
541 * Cancels an operation with the given identifier.
543 ArchiveManager.prototype.abort = function () {
544 var args = validator_.validateArgs(arguments, [
545 { name: "opId", type: types_.LONG }
548 var result = native_.callSync('ArchiveManager_abort', {opId: args.opId});
550 if (native_.isFailure(result)) {
551 throw native_.getErrorObject(result);
556 exports = new ArchiveManager();