[Filesystem] JavaScript part implementation
authorPawel Kaczmarek <p.kaczmarek3@samsung.com>
Mon, 16 Feb 2015 13:52:56 +0000 (14:52 +0100)
committerpius lee <pius.lee@samsung.com>
Tue, 17 Feb 2015 09:52:12 +0000 (18:52 +0900)
Inspired on NodeJs webapi-plugins implementation
NodeJS filesystem methods has been replaced with native methods

Change-Id: I76020be166c4ac5c2d0ef1d9dd00ea6301130eca
Signed-off-by: Pawel Kaczmarek <p.kaczmarek3@samsung.com>
src/filesystem/filesystem_api.js
src/filesystem/js/common.js [new file with mode: 0644]
src/filesystem/js/file.js [new file with mode: 0644]
src/filesystem/js/file_stream.js [new file with mode: 0644]
src/filesystem/js/file_system_manager.js [new file with mode: 0644]

index b27ab12560cc1fbbbc09e9f5b51037a58279b04b..724adc04f9600507ee102b4514f45bb48edfaf9d 100644 (file)
@@ -1,576 +1,8 @@
-/* global tizen, xwalk, extension */
-
 // Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-
-var utils_ = xwalk.utils;
-var type_ = utils_.type;
-var converter_ = utils_.converter;
-var validator_ = utils_.validator;
-var types_ = validator_.Types;
-var native_ = new xwalk.utils.NativeManager(extension);
-
-var callbackId = 0;
-var callbacks = {};
-
-function nextCallbackId() {
-  return callbackId++;
-}
-
-
-function SetReadOnlyProperty(obj, n, v) {
-  Object.defineProperty(obj, n, {value: v, writable: false});
-}
-
-var FileMode = {
-  r: 'r',
-  rw: 'rw',
-  w: 'w',
-  a: 'a'
-};
-var FileSystemStorageType = {
-  INTERNAL: 'INTERNAL',
-  EXTERNAL: 'EXTERNAL'
-};
-var FileSystemStorageState = {
-  MOUNTED: 'MOUNTED',
-  REMOVED: 'REMOVED',
-  UNMOUNTABLE: 'UNMOUNTABLE'
-};
-
-
-function FileSystemManager() {
-  SetReadOnlyProperty(this, 'maxPathLength', null);
-}
-
-
-FileSystemManager.prototype.resolve = function(location, onsuccess, onerror, mode) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'location', type: types_.STRING},
-    {name: 'onsuccess', type: types_.FUNCTION},
-    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true},
-    {name: 'mode', type: types_.ENUM, values: ['r', 'rw', 'w', 'a'], optional: true, nullable: true}
-  ]);
-
-  var data = {
-    location: args.location,
-    mode: args.mode
-  };
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
-      return;
-    }
-    native_.callIfPossible(args.onsuccess);
-  };
-
-  native_.call('FileSystemManager_resolve', data, callback);
-};
-
-FileSystemManager.prototype.getStorage = function(label, onsuccess, onerror) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'label', type: types_.STRING},
-    {name: 'onsuccess', type: types_.FUNCTION},
-    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
-  ]);
-
-  var data = {
-    label: args.label
-  };
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
-      return;
-    }
-    native_.callIfPossible(args.onsuccess);
-  };
-
-  native_.call('FileSystemManager_getStorage', data, callback);
-};
-
-FileSystemManager.prototype.listStorages = function(onsuccess, onerror) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'onsuccess', type: types_.FUNCTION},
-    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
-  ]);
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
-      return;
-    }
-    native_.callIfPossible(args.onsuccess);
-  };
-
-  native_.call('FileSystemManager_listStorages', {}, callback);
-};
-
-FileSystemManager.prototype.addStorageStateChangeListener = function(onsuccess, onerror) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'onsuccess', type: types_.FUNCTION},
-    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
-  ]);
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
-      return;
-    }
-    native_.callIfPossible(args.onsuccess);
-  };
-
-  native_.call('FileSystemManager_addStorageStateChangeListener', {}, callback);
-};
-
-FileSystemManager.prototype.removeStorageStateChangeListener = function(watchId) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'watchId', type: types_.LONG}
-  ]);
-
-  var data = {
-    watchId: args.watchId
-  };
-
-  var result = native_.callSync('FileSystemManager_removeStorageStateChangeListener', data);
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-};
-
-
-
-function File() {
-  Object.defineProperties(this, {
-    position: {
-      get: function() {},
-      set: function() {},
-      enumerable: true
-    },
-    readOnly: {
-      get: function() {},
-      set: function() {},
-      enumerable: true
-    },
-    isFile: {
-      get: function() {},
-      set: function() {},
-      enumerable: true
-    },
-    isDirectory: {
-      get: function() {},
-      set: function() {},
-      enumerable: true
-    },
-    created: {
-      get: function() {},
-      set: function() {},
-      enumerable: true
-    },
-    modified: {
-      get: function() {},
-      set: function() {},
-      enumerable: true
-    },
-    path: {
-      get: function() {},
-      set: function() {},
-      enumerable: true
-    },
-    name: {
-      get: function() {},
-      set: function() {},
-      enumerable: true
-    },
-    fullPath: {
-      get: function() {},
-      set: function() {},
-      enumerable: true
-    },
-    length: {
-      get: function() {},
-      set: function() {},
-      enumerable: true
-    }
-  });
-}
-
-
-File.prototype.toURI = function() {
-  var result = native_.callSync('File_toURI', {});
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-
-  return native_.getResultObject(result);
-};
-
-File.prototype.listFiles = function(onsuccess, onerror, filter) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'onsuccess', type: types_.FUNCTION},
-    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true},
-    {name: 'filter', type: types_.DICTIONARY, optional: true, nullable: true}
-  ]);
-
-  var data = {
-    filter: args.filter
-  };
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
-      return;
-    }
-    native_.callIfPossible(args.onsuccess);
-  };
-
-  native_.call('File_listFiles', data, callback);
-};
-
-File.prototype.openStream = function(mode, onsuccess, onerror, encoding) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'mode', type: types_.ENUM, values: ['r', 'rw', 'w', 'a']},
-    {name: 'onsuccess', type: types_.FUNCTION},
-    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true},
-    {name: 'encoding', type: types_.STRING, optional: true, nullable: true}
-  ]);
-
-  var data = {
-    mode: args.mode,
-    encoding: args.encoding
-  };
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
-      return;
-    }
-    native_.callIfPossible(args.onsuccess, new FileStream(native_.getResultObject(result)));
-  };
-
-  native_.call('File_openStream', data, callback);
-};
-
-File.prototype.readAsText = function(onsuccess, onerror, encoding) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'onsuccess', type: types_.FUNCTION},
-    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true},
-    {name: 'encoding', type: types_.STRING, optional: true, nullable: true}
-  ]);
-
-  var data = {
-    encoding: args.encoding
-  };
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
-      return;
-    }
-    native_.callIfPossible(args.onsuccess);
-  };
-
-  native_.call('File_readAsText', data, callback);
-};
-
-File.prototype.copyTo = function(originFilePath, destinationFilePath, overwrite, onsuccess, onerror) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'originFilePath', type: types_.STRING},
-    {name: 'destinationFilePath', type: types_.STRING},
-    {name: 'overwrite', type: types_.BOOLEAN},
-    {name: 'onsuccess', type: types_.FUNCTION, optional: true, nullable: true},
-    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
-  ]);
-
-  var data = {
-    originFilePath: args.originFilePath,
-    destinationFilePath: args.destinationFilePath,
-    overwrite: args.overwrite
-  };
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
-      return;
-    }
-    native_.callIfPossible(args.onsuccess);
-  };
-
-  native_.call('File_copyTo', data, callback);
-};
-
-File.prototype.moveTo = function(originFilePath, destinationFilePath, overwrite, onsuccess, onerror) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'originFilePath', type: types_.STRING},
-    {name: 'destinationFilePath', type: types_.STRING},
-    {name: 'overwrite', type: types_.BOOLEAN},
-    {name: 'onsuccess', type: types_.FUNCTION, optional: true, nullable: true},
-    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
-  ]);
-
-  var data = {
-    originFilePath: args.originFilePath,
-    destinationFilePath: args.destinationFilePath,
-    overwrite: args.overwrite
-  };
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
-      return;
-    }
-    native_.callIfPossible(args.onsuccess);
-  };
-
-  native_.call('File_moveTo', data, callback);
-};
-
-File.prototype.createDirectory = function(dirPath) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'dirPath', type: types_.STRING}
-  ]);
-
-  var data = {
-    dirPath: args.dirPath
-  };
-
-  var result = native_.callSync('File_createDirectory', data);
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-
-  var returnObject = new File(native_.getResultObject(result));
-  return returnObject;
-
-};
-
-File.prototype.createFile = function(relativeFilePath) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'relativeFilePath', type: types_.STRING}
-  ]);
-
-  var data = {
-    relativeFilePath: args.relativeFilePath
-  };
-
-  var result = native_.callSync('File_createFile', data);
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-
-  var returnObject = new File(native_.getResultObject(result));
-  return returnObject;
-
-};
-
-File.prototype.resolve = function(filePath) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'filePath', type: types_.STRING}
-  ]);
-
-  var data = {
-    filePath: args.filePath
-  };
-
-  var result = native_.callSync('File_resolve', data);
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-
-  var returnObject = new File(native_.getResultObject(result));
-  return returnObject;
-
-};
-
-File.prototype.deleteDirectory = function(directoryPath, recursive, onsuccess, onerror) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'directoryPath', type: types_.STRING},
-    {name: 'recursive', type: types_.BOOLEAN},
-    {name: 'onsuccess', type: types_.FUNCTION, optional: true, nullable: true},
-    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
-  ]);
-
-  var data = {
-    directoryPath: args.directoryPath,
-    recursive: args.recursive
-  };
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
-      return;
-    }
-    native_.callIfPossible(args.onsuccess);
-  };
-
-  native_.call('File_deleteDirectory', data, callback);
-
-};
-
-File.prototype.deleteFile = function(filePath, onsuccess, onerror) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'filePath', type: types_.STRING},
-    {name: 'onsuccess', type: types_.FUNCTION, optional: true, nullable: true},
-    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
-  ]);
-
-  var data = {
-    filePath: args.filePath
-  };
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
-      return;
-    }
-    native_.callIfPossible(args.onsuccess);
-  };
-
-  native_.call('File_deleteFile', data, callback);
-};
-
-
-function FileStream(fileDescriptor, nodeMode, nodeEncoding) {
-  Object.defineProperties(this, {
-    position: {
-      get: function() {},
-      enumerable: true,
-      writable: false
-    },
-    eof: {
-      get: function() {},
-      set: function() {},
-      enumerable: true
-    },
-    bytesAvailable: {
-      get: function() {},
-      enumerable: true,
-      writable: false
-    }
-  });
-}
-
-FileStream.prototype.close = function() {
-  var result = native_.callSync('FileStream_close', {});
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-};
-
-FileStream.prototype.read = function() {
-  var args = validator_.validateArgs(arguments, [
-    {
-      name: 'charCount',
-      type: types_.LONG
-    }
-  ]);
-
-  if (args.charCount <= 0) {
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
-        'Argument "charCount" must be greater than 0');
-  }
-
-  var result = native_.callSync('FileStream_read', {});
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-};
-
-FileStream.prototype.readBytes = function() {
-  var args = validator_.validateArgs(arguments, [
-    {
-      name: 'byteCount',
-      type: types_.LONG
-    }
-  ]);
-
-  if (args.byteCount <= 0) {
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
-        'Argument "byteCount" must be greater than 0');
-  }
-
-  var result = native_.callSync('FileStream_readBytes', {});
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-};
-
-FileStream.prototype.readBase64 = function() {
-  var args = validator_.validateArgs(arguments, [
-    {
-      name: 'byteCount',
-      type: types_.LONG
-    }
-  ]);
-
-  if (args.byteCount <= 0) {
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
-        'Argument "byteCount" must be greater than 0');
-  }
-
-  var result = native_.callSync('FileStream_readBase64', {});
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-};
-
-FileStream.prototype.write = function() {
-  var args = validator_.validateArgs(arguments, [
-    {
-      name: 'stringData',
-      type: types_.STRING
-    }
-  ]);
-
-  var result = native_.callSync('FileStream_write', {});
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-};
-
-FileStream.prototype.writeBytes = function() {
-  var args = validator_.validateArgs(arguments, [
-    {
-      name: 'byteData',
-      type: types_.ARRAY,
-      values: types_.OCTET
-    }
-  ]);
-
-  var result = native_.callSync('FileStream_writeBytes', {});
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-};
-
-FileStream.prototype.writeBase64 = function() {
-  var args = validator_.validateArgs(arguments, [
-    {
-      name: 'base64Data',
-      type: types_.STRING
-    }
-  ]);
-
-  var result = native_.callSync('FileStream_writeBase64', {});
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-};
-
-
-exports = new FileSystemManager();
+//= require('common.js');
+//= require('file_stream.js');
+//= require('file.js');
+//= require('file_system_manager.js');
diff --git a/src/filesystem/js/common.js b/src/filesystem/js/common.js
new file mode 100644 (file)
index 0000000..e1ca9c7
--- /dev/null
@@ -0,0 +1,209 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+var utils_ = xwalk.utils;
+var type_ = utils_.type;
+var converter_ = utils_.converter;
+var validator_ = utils_.validator;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+function SetReadOnlyProperty(obj, n, v) {
+  Object.defineProperty(obj, n, {value: v, writable: false});
+}
+
+var FileSystemStorageType = {
+  INTERNAL: 'INTERNAL',
+  EXTERNAL: 'EXTERNAL'
+};
+
+var FileSystemStorageState = {
+  MOUNTED: 'MOUNTED',
+  REMOVED: 'REMOVED',
+  UNMOUNTABLE: 'UNMOUNTABLE'
+};
+
+var FileMode = {
+  r: 'r',
+  rw: 'rw',
+  w: 'w',
+  a: 'a'
+};
+
+function CommonFS() {
+  Object.defineProperties(this, {
+    PRIVILEGE_FILESYSTEM_READ: {
+      value: 'http://tizen.org/privilege/filesystem.read',
+      writable: false,
+      enumerable: true
+    },
+    PRIVILEGE_FILESYSTEM_WRITE: {
+      value: 'http://tizen.org/privilege/filesystem.write',
+      writable: false,
+      enumerable: true
+    }
+  });
+}
+
+CommonFS.prototype.cacheVirtualToReal = {};
+
+CommonFS.prototype.cacheRealToVirtual = {};
+
+CommonFS.prototype.getFileInfo = function(aPath, aStatObj, secondIter, aMode) {
+  var _result = {},
+      _pathTokens,
+      _fileParentPath = '',
+      i;
+
+  if (aPath.indexOf('file://') === 0) {
+    aPath = aPath.substr('file://'.length);
+  }
+
+  if (aPath[0] === '/') {
+    aPath = aPath.substr(1);
+    _fileParentPath = '/';
+  }
+
+  _result.readOnly = aStatObj.readOnly;
+  _result.isFile = aStatObj.isFile;
+  _result.isDirectory = aStatObj.isDirectory;
+  _result.created = new Date(aStatObj.ctime * 1000);
+  _result.modified = new Date(aStatObj.mtime * 1000);
+  _result.fullPath = _fileParentPath + aPath;
+  _result.fileSize = aStatObj.size;
+  _result.mode = aMode;
+  if (_result.isDirectory) {
+    try {
+      _result.length = aStatObj.nlink;
+    } catch (err) {
+      _result.length = 0;
+    }
+  } else {
+    _result.length = undefined;
+  }
+
+  _pathTokens = aPath.split('/');
+  if (_pathTokens.length > 1) {
+    for (i = 0; i < _pathTokens.length - 1; ++i) {
+      _fileParentPath += _pathTokens[i] + '/';
+    }
+    _result.path = _fileParentPath;
+    _result.name = _pathTokens[_pathTokens.length - 1];
+    _result.parent = (secondIter) ? null : _fileParentPath;
+  } else {
+    _result.parent = null;
+    _result.path = _fileParentPath === '/' ? _fileParentPath : aPath;
+    _result.name = _fileParentPath === '/' ? aPath : '';
+  }
+  return _result;
+};
+
+CommonFS.prototype.isLocationAllowed = function(aPath) {
+  if (aPath.indexOf(this.cacheVirtualToReal.ringtones.path) === 0) {
+    return false;
+  }
+  if (aPath.indexOf(this.cacheVirtualToReal['wgt-package'].path) === 0) {
+    return false;
+  }
+
+  return true;
+};
+
+CommonFS.prototype.toRealPath = function(aPath) {
+  var _fileRealPath = '',
+      _uriPrefix = 'file://',
+      i;
+  if (aPath.indexOf(_uriPrefix) === 0) {
+    _fileRealPath = aPath.substr(_uriPrefix.length);
+  } else if (aPath[0] !== '/') {
+    //virtual path
+    var _pathTokens = aPath.split('/');
+    if (this.cacheVirtualToReal[_pathTokens[0]] && (
+        this.cacheVirtualToReal[_pathTokens[0]].state === undefined ||
+        this.cacheVirtualToReal[_pathTokens[0]].state === FileSystemStorageState.MOUNTED)) {
+      _fileRealPath = this.cacheVirtualToReal[_pathTokens[0]].path;
+      for (i = 1; i < _pathTokens.length; ++i) {
+        _fileRealPath += '/' + _pathTokens[i];
+      }
+    } else {
+      _fileRealPath = aPath;
+    }
+  } else {
+    _fileRealPath = aPath;
+  }
+
+  return _fileRealPath;
+};
+
+CommonFS.prototype.toVirtualPath = function(aPath) {
+  var _virtualPath = aPath;
+  if (_virtualPath.indexOf('file://') === 0) {
+    _virtualPath = _virtualPath.substr('file://'.length);
+  }
+  for (var real_path in this.cacheRealToVirtual) {
+    if (_virtualPath.indexOf(real_path) === 0) {
+      return _virtualPath.replace(
+          real_path,
+          this.cacheRealToVirtual[real_path]);
+    }
+  }
+
+  return aPath;
+};
+
+CommonFS.prototype.initCache = function(manager) {
+  if (manager._isWidgetPathFound) {
+    return;
+  }
+  var result = native_.callSync('Filesystem_getWidgetPaths', {});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  var widgetsPaths = native_.getResultObject(result);
+
+  this.cacheVirtualToReal['wgt-package'] = {
+    path: widgetsPaths['wgt-package'],
+    type: FileSystemStorageType.INTERNAL,
+    state: FileSystemStorageState.MOUNTED
+  };
+  this.cacheVirtualToReal['wgt-private'] = {
+    path: widgetsPaths['wgt-private'],
+    type: FileSystemStorageType.INTERNAL,
+    state: FileSystemStorageState.MOUNTED
+  };
+  this.cacheVirtualToReal['wgt-private-tmp'] = {
+    path: widgetsPaths['wgt-private-tmp'],
+    type: FileSystemStorageType.INTERNAL,
+    state: FileSystemStorageState.MOUNTED
+  };
+
+  this.cacheRealToVirtual[widgetsPaths['wgt-package']] = 'wgt-package';
+  this.cacheRealToVirtual[widgetsPaths['wgt-private']] = 'wgt-private';
+  this.cacheRealToVirtual[widgetsPaths['wgt-private-tmp']] = 'wgt-private-tmp';
+
+  var result = native_.callSync('FileSystemManager_fetchStorages', {});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var data = native_.getResultObject(result);
+
+  for (var i in data) {
+    if (data[i].state === FileSystemStorageState.MOUNTED) {
+      for (var j in data[i].paths) {
+        this.cacheVirtualToReal[j] = {
+          path: data[i].paths[j],
+          type: data[i].type,
+          state: data[i].state
+        };
+        this.cacheRealToVirtual[data[i].paths[j]] = j;
+      }
+    }
+  }
+  manager._isWidgetPathFound = true;
+
+};
+
+var commonFS_ = new CommonFS();
diff --git a/src/filesystem/js/file.js b/src/filesystem/js/file.js
new file mode 100644 (file)
index 0000000..dbb61fb
--- /dev/null
@@ -0,0 +1,293 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+function File(data) {
+  function fileSizeGetter() {
+    var _realPath = commonFS_.toRealPath(this.fullPath);
+    var _result = native_.callSync('File_statSync', {location: _realPath});
+    var _aStatObj = native_.getResultObject(_result);
+    return _aStatObj.isFile ? _aStatObj.size : undefined;
+  }
+
+  Object.defineProperties(this, {
+    parent: {
+      value: (function(data) {
+        try {
+          if (data.parent) { // prevent recursive - only one parent
+            var _parentPath = data.path.substr(0, data.path.length - 1);
+            var _location = {location: commonFS_.toRealPath(_parentPath)};
+            var _result = native_.callSync('File_statSync', _location);
+            var _statObj = native_.getResultObject(_result);
+            var _info = commonFS_.getFileInfo(_parentPath, _statObj, true);
+            return new File(_info);
+          } else {
+            return null;
+          }
+        } catch (err) {
+          console.log(err.name, err.message);
+          return null;
+        }
+      }(data)),
+      writable: false,
+      enumerable: true
+    },
+    readOnly: {value: data.readOnly, writable: false, enumerable: true},
+    isFile: {value: data.isFile, writable: false, enumerable: true},
+    isDirectory: {value: data.isDirectory, writable: false, enumerable: true},
+    created: {value: data.created, writable: false, enumerable: true},
+    modified: {value: data.modified, writable: false, enumerable: true},
+    path: {value: data.path, writable: false, enumerable: true},
+    name: {value: data.name, writable: false, enumerable: true},
+    fullPath: {value: data.fullPath, writable: false, enumerable: true},
+    fileSize: {enumerable: true, set: function() {
+    }, get: fileSizeGetter},
+    length: {value: data.length, writable: false, enumerable: true},
+    mode: {value: data.mode, writable: false},
+    f_isSubDir: {value: function(fullPathToCheck) {
+      return (-1 !== fullPathToCheck.indexOf(commonFS_.toRealPath(this.fullPath)));
+    }, writable: false},
+    f_isCorrectRelativePath: {value: function(relativePath) {
+      return ((-1 === relativePath.indexOf('/')) &&
+          (-1 === relativePath.indexOf('\\')) &&
+          (-1 === relativePath.indexOf('?')) &&
+          (-1 === relativePath.indexOf('*')) &&
+          (-1 === relativePath.indexOf(':')) &&
+          (-1 === relativePath.indexOf('"')) &&
+          (-1 === relativePath.indexOf('<')) &&
+          (-1 === relativePath.indexOf('>')));
+    }}
+  });
+}
+
+File.prototype.toURI = function() {
+  return 'file://' + commonFS_.toRealPath(this.fullPath);
+};
+
+File.prototype.listFiles = function(onsuccess, onerror, filter) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'onsuccess', type: types_.FUNCTION},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'filter', type: types_.DICTIONARY, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    filter: args.filter
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.onsuccess);
+  };
+
+  native_.call('File_listFiles', data, callback);
+};
+
+File.prototype.openStream = function(mode, onsuccess, onerror, encoding) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'mode', type: types_.ENUM, values: ['r', 'rw', 'w', 'a']},
+    {name: 'onsuccess', type: types_.FUNCTION},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'encoding', type: types_.STRING, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    mode: args.mode,
+    encoding: args.encoding
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.onsuccess, new FileStream(native_.getResultObject(result)));
+  };
+
+  native_.call('File_openStream', data, callback);
+};
+
+File.prototype.readAsText = function(onsuccess, onerror, encoding) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'onsuccess', type: types_.FUNCTION},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'encoding', type: types_.STRING, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    encoding: args.encoding
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.onsuccess);
+  };
+
+  native_.call('File_readAsText', data, callback);
+};
+
+File.prototype.copyTo = function(originFilePath, destinationFilePath, overwrite, onsuccess, onerror) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'originFilePath', type: types_.STRING},
+    {name: 'destinationFilePath', type: types_.STRING},
+    {name: 'overwrite', type: types_.BOOLEAN},
+    {name: 'onsuccess', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    originFilePath: args.originFilePath,
+    destinationFilePath: args.destinationFilePath,
+    overwrite: args.overwrite
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.onsuccess);
+  };
+
+  native_.call('File_copyTo', data, callback);
+};
+
+File.prototype.moveTo = function(originFilePath, destinationFilePath, overwrite, onsuccess, onerror) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'originFilePath', type: types_.STRING},
+    {name: 'destinationFilePath', type: types_.STRING},
+    {name: 'overwrite', type: types_.BOOLEAN},
+    {name: 'onsuccess', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    originFilePath: args.originFilePath,
+    destinationFilePath: args.destinationFilePath,
+    overwrite: args.overwrite
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.onsuccess);
+  };
+
+  native_.call('File_moveTo', data, callback);
+};
+
+File.prototype.createDirectory = function(dirPath) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'dirPath', type: types_.STRING}
+  ]);
+
+  var data = {
+    dirPath: args.dirPath
+  };
+
+  var result = native_.callSync('File_createDirectory', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var returnObject = new File(native_.getResultObject(result));
+  return returnObject;
+
+};
+
+File.prototype.createFile = function(relativeFilePath) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'relativeFilePath', type: types_.STRING}
+  ]);
+
+  var data = {
+    relativeFilePath: args.relativeFilePath
+  };
+
+  var result = native_.callSync('File_createFile', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var returnObject = new File(native_.getResultObject(result));
+  return returnObject;
+
+};
+
+File.prototype.resolve = function(filePath) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'filePath', type: types_.STRING}
+  ]);
+
+  var data = {
+    filePath: args.filePath
+  };
+
+  var result = native_.callSync('File_resolve', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var returnObject = new File(native_.getResultObject(result));
+  return returnObject;
+
+};
+
+File.prototype.deleteDirectory = function(directoryPath, recursive, onsuccess, onerror) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'directoryPath', type: types_.STRING},
+    {name: 'recursive', type: types_.BOOLEAN},
+    {name: 'onsuccess', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    directoryPath: args.directoryPath,
+    recursive: args.recursive
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.onsuccess);
+  };
+
+  native_.call('File_deleteDirectory', data, callback);
+
+};
+
+File.prototype.deleteFile = function(filePath, onsuccess, onerror) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'filePath', type: types_.STRING},
+    {name: 'onsuccess', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    filePath: args.filePath
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.onsuccess);
+  };
+
+  native_.call('File_deleteFile', data, callback);
+};
diff --git a/src/filesystem/js/file_stream.js b/src/filesystem/js/file_stream.js
new file mode 100644 (file)
index 0000000..ad9629e
--- /dev/null
@@ -0,0 +1,138 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+function FileStream(fileDescriptor, nodeMode, nodeEncoding) {
+  Object.defineProperties(this, {
+    position: {
+      get: function() {},
+      enumerable: true,
+      writable: false
+    },
+    eof: {
+      get: function() {},
+      set: function() {},
+      enumerable: true
+    },
+    bytesAvailable: {
+      get: function() {},
+      enumerable: true,
+      writable: false
+    }
+  });
+}
+
+FileStream.prototype.close = function() {
+  var result = native_.callSync('FileStream_close', {});
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+FileStream.prototype.read = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'charCount',
+      type: types_.LONG
+    }
+  ]);
+
+  if (args.charCount <= 0) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
+        'Argument "charCount" must be greater than 0');
+  }
+
+  var result = native_.callSync('FileStream_read', {});
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+FileStream.prototype.readBytes = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'byteCount',
+      type: types_.LONG
+    }
+  ]);
+
+  if (args.byteCount <= 0) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
+        'Argument "byteCount" must be greater than 0');
+  }
+
+  var result = native_.callSync('FileStream_readBytes', {});
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+FileStream.prototype.readBase64 = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'byteCount',
+      type: types_.LONG
+    }
+  ]);
+
+  if (args.byteCount <= 0) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
+        'Argument "byteCount" must be greater than 0');
+  }
+
+  var result = native_.callSync('FileStream_readBase64', {});
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+FileStream.prototype.write = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'stringData',
+      type: types_.STRING
+    }
+  ]);
+
+  var result = native_.callSync('FileStream_write', {});
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+FileStream.prototype.writeBytes = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'byteData',
+      type: types_.ARRAY,
+      values: types_.OCTET
+    }
+  ]);
+
+  var result = native_.callSync('FileStream_writeBytes', {});
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+FileStream.prototype.writeBase64 = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'base64Data',
+      type: types_.STRING
+    }
+  ]);
+
+  var result = native_.callSync('FileStream_writeBase64', {});
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
diff --git a/src/filesystem/js/file_system_manager.js b/src/filesystem/js/file_system_manager.js
new file mode 100644 (file)
index 0000000..995c790
--- /dev/null
@@ -0,0 +1,197 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function FileSystemStorage(data) {
+  Object.defineProperties(this, {
+    label: {value: data.label, writable: false, enumerable: true},
+    type: {value: data.type, writable: false, enumerable: true},
+    state: {value: data.state, writable: false, enumerable: true}
+  });
+}
+
+var PATH_MAX = 4096;
+
+function FileSystemManager() {
+  Object.defineProperties(this, {
+    maxPathLength: {value: PATH_MAX, writable: false, enumerable: true},
+    _isWidgetPathFound: {value: false, writable: true}
+  });
+}
+
+FileSystemManager.prototype.resolve = function(location, onsuccess, onerror, mode) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'location', type: types_.STRING},
+    {name: 'onsuccess', type: types_.FUNCTION},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'mode', type: types_.ENUM, values: Object.keys(FileMode), optional: true, nullable: true}
+  ]);
+
+  if (!args.has.mode) {
+    args.mode = 'rw';
+  }
+  commonFS_.initCache(this);
+
+  if (args.location[0] === '/') {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR,
+          'Global path without \'file://\' prefix is not valid.'));
+    }, 0);
+    return;
+  }
+  var _realPath = commonFS_.toRealPath(args.location);
+  var _isLocationAllowed = commonFS_.isLocationAllowed(_realPath);
+
+  if (args.mode !== 'r' && !_isLocationAllowed) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
+          'Provided arguments are not valid.'));
+    }, 0);
+    return;
+  }
+
+  var data = {
+    location: _realPath
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+      return;
+    }
+
+    var aStatObj = native_.getResultObject(result);
+
+    var _result;
+    var _path = (args.location.indexOf('file://') === 0) ?
+            commonFS_.toVirtualPath(args.location) : args.location;
+    if (_path[_path.length - 1] === '/') {
+      _path = _path.substr(0, _path.length - 1);
+    }
+    _result = commonFS_.getFileInfo(_path, aStatObj, false, args.mode);
+    if (_result.readOnly && args.mode !== 'r') {
+      throw new tizen.WebAPIException(tizen.WebAPIException.IO_ERR);
+    } else {
+      native_.callIfPossible(args.onsuccess, new File(_result));
+    }
+  };
+
+  native_.call('File_stat', data, callback);
+};
+
+FileSystemManager.prototype.getStorage = function(label, onsuccess, onerror) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'label', type: types_.STRING},
+    {name: 'onsuccess', type: types_.FUNCTION},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  commonFS_.initCache(this);
+
+  var cachedObj = commonFS_.cacheVirtualToReal[args.label];
+  if (undefined === cachedObj) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR,
+          'Storage not found.'));
+    }, 0);
+  } else {
+    setTimeout(function() {
+      var storage = new FileSystemStorage({
+        label: args.label,
+        type: cachedObj.type,
+        state: cachedObj.state
+      });
+      native_.callIfPossible(args.onsuccess, storage);
+    }, 0);
+  }
+};
+
+FileSystemManager.prototype.listStorages = function(onsuccess, onerror) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'onsuccess', type: types_.FUNCTION},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  commonFS_.initCache(this);
+
+  var _storages = [];
+
+  for (var _storage in commonFS_.cacheVirtualToReal) {
+    var storageObj = commonFS_.cacheVirtualToReal[_storage];
+    _storages.push(new FileSystemStorage({
+      label: _storage,
+      type: storageObj.type ? storageObj.type : FileSystemStorageType.INTERNAL,
+      state: storageObj.state ? storageObj.state : FileSystemStorageState.MOUNTED
+    }));
+  }
+
+  setTimeout(function() {args.onsuccess(_storages);}, 0);
+
+};
+
+var callbackId = 0;
+var callbacks = {};
+
+function nextCallbackId() {
+  return callbackId++;
+}
+
+function _StorageStateChangeListener(result) {
+  var storage = new FileSystemStorage(native_.getResultObject(result));
+  for (var id in callbacks) {
+    if (callbacks.hasOwnProperty(id)) {
+      native_.callIfPossible(callbacks[id].onsuccess, storage);
+    }
+  }
+}
+
+FileSystemManager.prototype.addStorageStateChangeListener = function(onsuccess, onerror) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'onsuccess', type: types_.FUNCTION},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var register = false;
+  if (type_.isEmptyObject(callbacks)) {
+    register = true;
+  }
+
+  var id = nextCallbackId();
+  callbacks[id] = args.onsuccess;
+
+  if (register) {
+    native_.addListener('StorageStateChangeListener', _StorageStateChangeListener);
+
+    var result = native_.callSync('FileSystemManager_addStorageStateChangeListener', {});
+
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+      return;
+    }
+  }
+
+  return id;
+};
+
+FileSystemManager.prototype.removeStorageStateChangeListener = function(watchId) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'watchId', type: types_.LONG}
+  ]);
+
+  var id = args.watchId;
+
+  if (type_.isNullOrUndefined(callbacks[id])) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR, 'Watch ID not found.');
+  }
+
+  delete callbacks[id];
+
+  if (type_.isEmptyObject(callbacks)) {
+    native_.callSync('FileSystemManager_removeStorageStateChangeListener', id);
+  }
+};
+
+exports = new FileSystemManager();