From: Pawel Andruszkiewicz Date: Fri, 8 Apr 2016 08:34:50 +0000 (+0200) Subject: [File] Code structure changed to match cordova architecture. X-Git-Tag: submit/tizen/20160411.115901^2~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=05de6f94fc3ad0ba88d7f3d2bb397e82aa85d487;p=platform%2Fcore%2Fapi%2Fcordova-plugins.git [File] Code structure changed to match cordova architecture. Change-Id: I12878d562c57285b483dbcee02a7191fbb105f9c Signed-off-by: Pawel Andruszkiewicz --- diff --git a/src/cordova/cordova_api.js b/src/cordova/cordova_api.js index 516c2bc..92438ce 100755 --- a/src/cordova/cordova_api.js +++ b/src/cordova/cordova_api.js @@ -52,8 +52,5 @@ exports = { } } }); - - // load file native plugin - tizen.cordova.file(require); } }; diff --git a/src/file/cordova_file_api.js b/src/file/cordova_file_api.js index b5a171d..a87e834 100755 --- a/src/file/cordova_file_api.js +++ b/src/file/cordova_file_api.js @@ -14,17 +14,26 @@ * limitations under the License. */ -//= require('Errors.js'); -//= require('rootsUtils.js'); -//= require('DirectoryEntry.js'); -//= require('DirectoryReader.js'); -//= require('Entry.js'); -//= require('FileReader.js'); -//= require('fileSystemPaths.js'); -//= require('fileSystems-roots.js'); -//= require('FileWriter.js'); -//= require('requestFileSystem.js'); -//= require('resolveLocalFileSystemURI.js'); +var native_ = new xwalk.utils.NativeManager(extension); -//= require('FileSystem.js'); -//= require('File.js'); +function FileManager() {} + +FileManager.prototype.truncate = function(uri, length, successCallback, errorCallback) { + var callArgs = { + 'uri': uri, + 'length': length + }; + + var result = native_.callSync('File_truncate', callArgs); + if (native_.isFailure(result)) { + if (errorCallback) { + errorCallback(native_.getErrorObject(result)); + } + } else { + if (successCallback) { + successCallback(length); + } + } +}; + +exports = new FileManager(); diff --git a/src/file/js/DirectoryEntry.js b/src/file/js/DirectoryEntry.js deleted file mode 100644 index 3f11fd4..0000000 --- a/src/file/js/DirectoryEntry.js +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// TODO: remove when added to public cordova repository -> begin -cordova.define('cordova-plugin-file.tizen.DirectoryEntry', function(require, exports, module) { -// TODO: remove -> end - - function sanitizePath(path) { - var prepend = '/' === path[0]; - var input = path.split('/'); - var output = []; - - for (var i = 0; i < input.length; ++i) { - var part = input[i]; - switch (part) { - case '': - case '.': - // ignore - break; - - case '..': - // remove previous part - output.pop(); - break; - - default: - output.push(part); - break; - } - } - - return (prepend ? '/' : '') + output.join('/'); - } - - var getFunction = function(successCallback, errorCallback, args, isDirectory) { - var uri = rootsUtils.internalUrlToNativePath(args[0]), - path = rootsUtils.stripTrailingSlash(args[1]), - options = args[2] || {}, - create_flag = !!options.create, - exclusive_flag = !!options.exclusive, - absolute_path = ''; - - if (!uri) { - errorCallback && errorCallback(FileError.ENCODING_ERR); - return; - } - - if ('/' === path[0]) { - // path seems absolute, checking if path is a child of this object URI - if (0 === path.indexOf(uri)) { - // path is child - OK - absolute_path = path; - } else { - // path is not a child - calling error callback - console.error('Error - path is not a child of current directory entry') - errorCallback && errorCallback(FileError.INVALID_STATE_ERR); - return; - } - } else { - // path seems to be relative path, combining absolute path - absolute_path = uri + '/' + path; - } - - var root = rootsUtils.findFilesystem(absolute_path).nativeURL; - var clean_path = sanitizePath(absolute_path); - - if (0 !== clean_path.indexOf(root)) { - // we went above the root directory, force the absolute path to be - // at least in that directory - clean_path = root + '/' + sanitizePath(absolute_path.substring(root.length + 1)); - } - - var parent_path = clean_path.substring(0, clean_path.lastIndexOf('/')); - var child_name = clean_path.substring(clean_path.lastIndexOf('/') + 1); - - if (!rootsUtils.isValidFileName(child_name)) { - console.error('Disallowed character detected in file name: ' + child_name); - errorCallback && errorCallback(FileError.ENCODING_ERR); - return; - } - - var resolveSuccess = function(dir) { - // clean_path points to existing destination - if (create_flag && exclusive_flag) { - console.error('Error while resolving dir - already exist dir'); - errorCallback && errorCallback(FileError.PATH_EXISTS_ERR); - } else if (!create_flag && dir.isDirectory !== isDirectory) { - console.error('Error while resolving dir - already exist file'); - errorCallback && errorCallback(FileError.TYPE_MISMATCH_ERR); - } else { - successCallback && successCallback(rootsUtils.createEntry(dir)); - } - }; - - var resolveError = function(e) { - if (create_flag) { - // should create directory - try { - // resolve parent - tizen.filesystem.resolve(parent_path, - function(dir) { - // create object - var new_obj; - if (isDirectory) { - new_obj = dir.createDirectory(child_name); - } else { - new_obj = dir.createFile(child_name); - } - - successCallback && successCallback(rootsUtils.createEntry(new_obj)); - }, - function () { - console.error('Error - immediate parent does not exist'); - errorCallback && errorCallback(FileError.INVALID_STATE_ERR); - }, - 'rw' - ); - } catch (err) { - console.error('Error - Could not resolve'); - errorCallback && errorCallback(ConvertTizenFileError(err)); - } - } else { - console.error('Error - create flag is false - new directory would not be created'); - errorCallback && errorCallback(FileError.NOT_FOUND_ERR); - } - }; - - // try to resolve - try { - tizen.filesystem.resolve(clean_path, resolveSuccess, resolveError, 'rw'); - } catch (err) { - console.error('Error - Could not resolve'); - errorCallback && errorCallback(ConvertTizenFileError(err)); - } - }; - -module.exports = { - getDirectory: function(successCallback, errorCallback, args) { - getFunction(successCallback, errorCallback, args, true); - }, - removeRecursively: function(successCallback, errorCallback, args) { - var uri = rootsUtils.internalUrlToNativePath(args[0]); - - if (!uri) { - errorCallback && errorCallback(FileError.ENCODING_ERR); - return; - } - - if (rootsUtils.isRootUri(uri)) { - console.error('It is not allowed to remove root directory.'); - errorCallback && errorCallback(FileError.NO_MODIFICATION_ALLOWED_ERR); - return; - } - - // resolve parent - var tmp_path = uri[uri.length-1] === '/' ? uri.substring(0, uri.lastIndexOf('/')) : uri; - var parent_path = tmp_path.substring(0, tmp_path.lastIndexOf('/')+1); - try { - tizen.filesystem.resolve( - parent_path, - function(dir) { - try { - if (dir.isDirectory) { - dir.deleteDirectory( - uri, - true, - function() { - successCallback && successCallback(); - }, function(e) { - console.error('Error - recursively deletion failed'); - errorCallback && errorCallback(FileError.NO_MODIFICATION_ALLOWED_ERR); - }); - } else { - console.error('Error - entry is not a directory'); - errorCallback && errorCallback(FileError.INVALID_STATE_ERR); - } - } catch (err) { - console.error('Error - Could not deleteDirectory'); - errorCallback && errorCallback(ConvertTizenFileError(err)); - } - }, function(e) { - console.error('Error: ' + e.message); - errorCallback && errorCallback(ConvertTizenFileError(e)); - }, 'rw' - ); - } catch (err) { - console.error('Error - Could not resolve'); - errorCallback && errorCallback(ConvertTizenFileError(err)); - } - }, - getFile: function(successCallback, errorCallback, args) { - getFunction(successCallback, errorCallback, args, false); - } -}; - -//TODO: remove when added to public cordova repository -> begin -}); -//TODO: remove -> end diff --git a/src/file/js/DirectoryReader.js b/src/file/js/DirectoryReader.js deleted file mode 100644 index 6feed91..0000000 --- a/src/file/js/DirectoryReader.js +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// TODO: remove when added to public cordova repository -> begin -cordova.define('cordova-plugin-file.tizen.DirectoryReader', function(require, exports, module) { -// TODO: remove -> end - -module.exports = { - readEntries: function(successCallback, errorCallback, args) { - var uri = rootsUtils.internalUrlToNativePath(args[0]); - - if (!uri) { - errorCallback && errorCallback(FileError.ENCODING_ERR); - return; - } - - var fail = function(e) { - errorCallback && errorCallback(ConvertTizenFileError(e)); - } - try { - tizen.filesystem.resolve(uri, - function (f) { - f.listFiles(function(v) { - var retVal = []; - for (var i = 0; i < v.length; ++i) { - var obj = rootsUtils.createEntry(v[i], rootsUtils.findFilesystem(v[i].toURI()).filesystemName); - obj.isDirectory = v[i].isDirectory; - obj.isFile = v[i].isFile; - retVal.push(obj); - }; - successCallback(retVal); - }, fail); - }, fail, 'r'); - } catch (e) { - fail(e); - } - } -}; - -//TODO: remove when added to public cordova repository -> begin -}); -//TODO: remove -> end diff --git a/src/file/js/Entry.js b/src/file/js/Entry.js deleted file mode 100644 index 1b258e8..0000000 --- a/src/file/js/Entry.js +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// TODO: remove when added to public cordova repository -> begin -cordova.define('cordova-plugin-file.tizen.Entry', function(require, exports, module) { -// TODO: remove -> end - -var resolveParent = function(srcURL, errorCallback, rest){ - try { - tizen.filesystem.resolve( - srcURL, - function (srcFile) { - var parentDir = srcFile.parent; - if (!parentDir) { - console.error('Error - could not resolve file ' + srcURL); - errorCallback && errorCallback(FileError.ENCODING_ERR); - } else { - rest(srcFile, parentDir); - } - }, function (err) { - console.error('Error - resolve file ' + srcURL + ' failed'); - errorCallback && errorCallback(ConvertTizenFileError(err)); - }, - 'r'); - } catch (exception) { - console.error('Error - resolve ' + srcURL + ' file thrown exception'); - errorCallback && errorCallback(ConvertTizenFileError(exception)); - } -}; - -var changeFile = function(method, successCallback, errorCallback, args) { - var srcURL = rootsUtils.internalUrlToNativePath(args[0]); - var name = args[2]; - var destDir = rootsUtils.internalUrlToNativePath(args[1]); - var destURL = destDir + '/' + name; - - function fail(e, msg) { - console.error(msg); - if (errorCallback) { - errorCallback(e); - } - } - - if (!srcURL || !destDir) { - fail(FileError.ENCODING_ERR, 'Error - Failed to decode internal URL.'); - return; - } - - if (!rootsUtils.isValidFileName(name)) { - fail(FileError.ENCODING_ERR, 'Error - Disallowed character detected in the file name: ' + name); - return; - } - - if (-1 !== (destURL + '/').indexOf(srcURL + '/')) { - fail(FileError.INVALID_MODIFICATION_ERR, 'Error - Cannot copy/move onto itself.'); - return; - } - - function performAction(srcFile, parentDir) { - try { - parentDir[method](srcFile.fullPath, - destURL, - true, - function () { - try { - tizen.filesystem.resolve( - destURL, - function (destFile) { - var destEntry = rootsUtils.createEntry(destFile); - destEntry.isDirectory = destFile.isDirectory; - successCallback && successCallback(destEntry); - }, function (err) { - fail(ConvertTizenFileError(err), 'Error - resolve result entry failed'); - } - ); - } catch (exception) { - fail(ConvertTizenFileError(exception), 'Error - resolve result entry thrown exception'); - } - }, function (err) { - fail(ConvertTizenFileError(err), 'Error - ' + method + ' operation failed'); - } - ); - } catch (exception) { - fail(ConvertTizenFileError(exception), 'Error - ' + method + ' operation thrown exception'); - } - } - - try { - tizen.filesystem.resolve(destDir, function(d) { - resolveParent (srcURL, errorCallback, - function(srcFile, parentDir) { - try { - // check if destination entry exists - tizen.filesystem.resolve(destURL, function(d) { - // destination exists, we may proceed only if it's the same type - // as source - if (d.isFile === srcFile.isFile && d.isDirectory === srcFile.isDirectory) { - performAction(srcFile, parentDir); - } else { - fail(FileError.INVALID_MODIFICATION_ERR, 'Error - source and destination have mismatched types'); - } - }, function() { - // error means that we're safe to proceed - performAction(srcFile, parentDir); - }, 'r'); - } catch (exception) { - fail(ConvertTizenFileError(exception), 'Error - resolve destination entry threw exception'); - } - } - ); - }, function() { - fail(FileError.NOT_FOUND_ERR, 'Error - destination directory does not exist'); - }, 'r'); - } catch (e) { - fail(ConvertTizenFileError(e), 'Error - resolve destination directory threw exception'); - } -}; - -module.exports = { - getFileMetadata: function(successCallback, errorCallback, args) { - var uri = rootsUtils.internalUrlToNativePath(args[0]); - if (!uri) { - errorCallback && errorCallback(FileError.ENCODING_ERR); - return; - } - try { - tizen.filesystem.resolve(uri, function (file) { - var result = { 'size': file.fileSize, 'lastModifiedDate': file.modified }; - successCallback && successCallback(result); - }, function (err) { - errorCallback && errorCallback(ConvertTizenFileError(err)); - }, 'r'); - } catch (exception) { - console.error('Error - resolve failed'); - errorCallback && errorCallback(ConvertTizenFileError(exception)); - } - }, - setMetadata: function(successCallback, errorCallback, args) { - console.error('setMetadata - Not supported'); - errorCallback && errorCallback(FileError.ENCODING_ERR); - }, - moveTo: function(successCallback, errorCallback, args) { - changeFile('moveTo', successCallback, errorCallback, args); - }, - copyTo: function(successCallback, errorCallback, args) { - changeFile('copyTo', successCallback, errorCallback, args); - }, - remove: function(successCallback, errorCallback, args) { - var url = rootsUtils.internalUrlToNativePath(args[0]); - - if (!url) { - errorCallback && errorCallback(FileError.ENCODING_ERR); - return; - } - - if (rootsUtils.isRootUri(url)) { - console.error('It is not allowed to remove root directory.'); - errorCallback && errorCallback(FileError.NO_MODIFICATION_ALLOWED_ERR); - return; - } - - resolveParent(url, errorCallback, - function(srcFile, parentDir){ - var method = srcFile.isFile ? 'deleteFile' : 'deleteDirectory'; - var args = [srcFile.fullPath, - false, - function() {successCallback && successCallback();}, - function(err) { - console.error('Error - ' + method + ' failed'); - errorCallback && errorCallback(ConvertTizenFileError(err)); - }]; - if (srcFile.isFile) { - //remove recursive flag - args.splice(1, 1); - } - try { - parentDir[method].apply(parentDir, args); - } catch (exception) { - console.error('Error - ' + method + ' thrown exception ' + JSON.stringify(exception)); - errorCallback && errorCallback(ConvertTizenFileError(exception)); - } - } - ); - }, - getParent: function(successCallback, errorCallback, args) { - var url = rootsUtils.internalUrlToNativePath(args[0]); - - if (!url) { - errorCallback && errorCallback(FileError.ENCODING_ERR); - return; - } - - if (rootsUtils.isRootUri(url)) { - successCallback && successCallback(rootsUtils.findFilesystem(url)); - return; - } - - resolveParent(url, errorCallback, - function(srcFile, parentDir){ - successCallback && successCallback(rootsUtils.createEntry(srcFile.parent)); - } - ); - } -}; - -//TODO: remove when added to public cordova repository -> begin -}); -//TODO: remove -> end diff --git a/src/file/js/Errors.js b/src/file/js/Errors.js deleted file mode 100644 index 89080f5..0000000 --- a/src/file/js/Errors.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Function converting a Tizen error to a cordova error - * - * {unsigned short} WebAPIError error - */ -function ConvertTizenFileError(err) { - switch (err.name) { - case 'InvalidValuesError': - return FileError.ENCODING_ERR; - - case 'NotFoundError': - return FileError.NOT_FOUND_ERR; - - case 'IOError': - return FileError.INVALID_MODIFICATION_ERR; - - default: - return FileError.ENCODING_ERR; - } -} diff --git a/src/file/js/File.js b/src/file/js/File.js deleted file mode 100644 index fd6bcd1..0000000 --- a/src/file/js/File.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// TODO: remove when added to public cordova repository -> begin -var plugin_name = 'cordova-plugin-file.tizen.File'; - -cordova.define(plugin_name, function(require, exports, module) { -// TODO: remove -> end - -var modules = [ - 'DirectoryEntry', - 'DirectoryReader', - 'Entry', - 'FileReader', - 'fileSystemPaths', - 'fileSystems-roots', - 'FileWriter', - 'requestFileSystem', - 'resolveLocalFileSystemURI' -]; - -// merge methods from submodules into this one -for (var i = 0; i < modules.length; ++i) { - var m = require('cordova-plugin-file.tizen.' + modules[i]); - for (var prop in m) { - if (m.hasOwnProperty(prop)) { - exports[prop] = m[prop]; - } - } -} - -require("cordova/exec/proxy").add("File", exports); - -console.log('Loaded cordova.file API'); - -// TODO: remove when added to public cordova repository -> begin -}); - -exports = function(require) { - require('cordova-tizen').addPlugin('cordova-plugin-file.File', plugin_name, 'runs'); - require('cordova-tizen').addPlugin('cordova-plugin-file.FileSystem', 'cordova-plugin-file.tizen.FileSystem', 'merges', 'window.FileSystem'); -}; -// TODO: remove -> end diff --git a/src/file/js/FileReader.js b/src/file/js/FileReader.js deleted file mode 100644 index d724459..0000000 --- a/src/file/js/FileReader.js +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// TODO: remove when added to public cordova repository -> begin -cordova.define('cordova-plugin-file.tizen.FileReader', function(require, exports, module) { -// TODO: remove -> end - -function read(operation, url, start, end, successCallback, errorCallback, encoding) { - url = rootsUtils.internalUrlToNativePath(url); - - if (!url) { - errorCallback && errorCallback(FileError.ENCODING_ERR); - return; - } - - var fail = function(e) { - errorCallback && errorCallback(ConvertTizenFileError(e)); - } - var win = function(size) { - successCallback && successCallback(size); - } - try { - tizen.filesystem.resolve(url, function(file) { - if (0 === end - start) { - // nothing to read, report success - win(); - } else { - try { - file.openStream('r', function(stream) { - try { - stream.position = start; - var r = stream[operation](end - start); - stream.close(); - win(r); - } catch (e) { - fail(e); - } - }, fail, encoding); - } catch (e) { - fail(e); - } - } - }, fail, 'r'); - } catch (e) { - fail(e); - } -} - -module.exports = { - readAsText: function(successCallback, errorCallback, args) { - read('read', args[0], args[2], args[3], function(r) { - successCallback && successCallback(r || ''); - }, errorCallback, args[1]); - }, - readAsDataURL: function(successCallback, errorCallback, args) { - read('readBase64', args[0], args[1], args[2], function(r) { - r = 'data:;base64,' + (r || ''); // MIME is missing because it's not passed to exec() - successCallback && successCallback(r); - }, errorCallback); - }, - readAsBinaryString: function(successCallback, errorCallback, args) { - read('readBytes', args[0], args[1], args[2], function(r) { - r = r || []; - var str = ''; - // this may be not so efficient, but - // String.fromCharCode.apply(null, r); - // may throw if r.length is large enough - for (var i = 0; i < r.length; ++i) { - str += String.fromCharCode(r[i]); - } - successCallback && successCallback(str); - }, errorCallback); - }, - readAsArrayBuffer: function(successCallback, errorCallback, args) { - read('readBytes', args[0], args[1], args[2], function(r) { - successCallback && successCallback(r || []); - }, errorCallback); - }, -}; - -//TODO: remove when added to public cordova repository -> begin -}); -//TODO: remove -> end diff --git a/src/file/js/FileSystem.js b/src/file/js/FileSystem.js deleted file mode 100644 index 8eacf99..0000000 --- a/src/file/js/FileSystem.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// TODO: remove when added to public cordova repository -> begin -cordova.define('cordova-plugin-file.tizen.FileSystem', function(require, exports, module) { -// TODO: remove -> end - -module.exports = { - __format__: function(fullPath) { - return 'cdvfile://localhost/' + this.name + fullPath; - } -}; - -console.log('Loaded cordova.file FileSystem'); - -// TODO: remove when added to public cordova repository -> begin -}); -// TODO: remove -> end diff --git a/src/file/js/FileWriter.js b/src/file/js/FileWriter.js deleted file mode 100644 index 9150723..0000000 --- a/src/file/js/FileWriter.js +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// TODO: remove when added to public cordova repository -> begin -cordova.define('cordova-plugin-file.tizen.FileWriter', function(require, exports, module) { -// TODO: remove -> end - -var utils_ = xwalk.utils; -var native_ = new utils_.NativeManager(extension); - -// https://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array -function toUTF8Array(str) { - var utf8 = []; - for (var i = 0; i < str.length; ++i) { - var charcode = str.charCodeAt(i); - if (charcode < 0x80) utf8.push(charcode); - else if (charcode < 0x800) { - utf8.push(0xc0 | (charcode >> 6), - 0x80 | (charcode & 0x3f)); - } - else if (charcode < 0xd800 || charcode >= 0xe000) { - utf8.push(0xe0 | (charcode >> 12), - 0x80 | ((charcode>>6) & 0x3f), - 0x80 | (charcode & 0x3f)); - } - // surrogate pair - else { - i++; - // UTF-16 encodes 0x10000-0x10FFFF by - // subtracting 0x10000 and splitting the - // 20 bits of 0x0-0xFFFFF into two halves - charcode = 0x10000 + (((charcode & 0x3ff)<<10) - | (str.charCodeAt(i) & 0x3ff)); - utf8.push(0xf0 | (charcode >>18), - 0x80 | ((charcode>>12) & 0x3f), - 0x80 | ((charcode>>6) & 0x3f), - 0x80 | (charcode & 0x3f)); - } - } - return utf8; -} - -module.exports = { - write: function(successCallback, errorCallback, args) { - var uri = rootsUtils.internalUrlToNativePath(args[0]); - var data = args[1]; - var position = args[2]; - var isBinary = args[3]; - - if (!uri) { - errorCallback && errorCallback(FileError.ENCODING_ERR); - return; - } - - if (!isBinary) { - if ('string' === typeof data) { - // convert to UTF-8, as this is the default encoding for read operations - data = toUTF8Array(data); - } else { - // we don't support other types - errorCallback && errorCallback(FileError.TYPE_MISMATCH_ERR); - return; - } - } else { - if (data instanceof ArrayBuffer) { - var a = new Uint8Array(data); - data = []; - for (var i = 0; i < a.length; ++i) { - data.push(a[i]); - } - } else { - // we don't support other types - errorCallback && errorCallback(FileError.TYPE_MISMATCH_ERR); - return; - } - } - - var onSuccess = function (file) { - if (file.isDirectory) { - errorCallback && errorCallback(FileError.INVALID_MODIFICATION_ERR); - return; - } - - var openStreamSuccess = function (stream) { - try { - stream.position = position; - stream.writeBytes(data); - var length = stream.position - position; - stream.close(); - - // The cordova documentation points to: http://dev.w3.org/2009/dap/file-system/file-writer.html - // This spec states that file length after write operation should be the greater of - // (pre-write length) and (pre-write position + data.size), however - // the cordova implementation sets it to the latter. In order to accommodate - // for this, we need to truncate after write... - module.exports.truncate(function() { - successCallback && successCallback(length); - }, errorCallback, [args[0], stream.position]); - } catch (error) { - errorCallback && errorCallback(ConvertTizenFileError(error)); - } - } - - var openStreamError = function (error) { - errorCallback && errorCallback(ConvertTizenFileError(error)); - } - - try { - file.openStream('rw', openStreamSuccess, openStreamError); - } catch (error) { - errorCallback && errorCallback(ConvertTizenFileError(error)); - } - } - - var onError = function (error) { - errorCallback && errorCallback(ConvertTizenFileError(error)); - } - - try { - tizen.filesystem.resolve(uri, onSuccess, onError, 'rw'); - } catch (error) { - errorCallback && errorCallback(ConvertTizenFileError(error)); - } - }, - - truncate: function(successCallback, errorCallback, args) { - var uri = rootsUtils.internalUrlToNativePath(args[0]); - var length = args[1]; - - if (!uri) { - errorCallback && errorCallback(FileError.ENCODING_ERR); - return; - } - - var uriPrefix = 'file://'; - if (0 === uri.indexOf(uriPrefix)) { - uri = uri.substring(uriPrefix.length); - } - - var callArgs = { - 'uri': uri, - 'length': length - }; - - var result = native_.callSync('File_truncate', callArgs); - if (native_.isFailure(result)) { - errorCallback && errorCallback(ConvertTizenFileError(native_.getErrorObject(result))); - } else { - successCallback && successCallback(length); - } - } -}; - -//TODO: remove when added to public cordova repository -> begin -}); -//TODO: remove -> end diff --git a/src/file/js/fileSystemPaths.js b/src/file/js/fileSystemPaths.js deleted file mode 100644 index ec1bb69..0000000 --- a/src/file/js/fileSystemPaths.js +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// TODO: remove when added to public cordova repository -> begin -cordova.define('cordova-plugin-file.tizen.fileSystemPaths', function(require, exports, module) { -// TODO: remove -> end - -var pathsPrefix = { - sharedDirectory: 'file:///opt/usr/media/' -}; - -function setExternalStorage(callback) { - var label = ''; - - var onError = function(error) { - console.error('Failed to get external storage: ' + error.message); - callback(pathsPrefix); - } - - var onSuccess = function(storages) { - for (var i = 0; i < storages.length; ++i) { - if (storages[i].type === 'EXTERNAL' && storages[i].state === 'MOUNTED') { - label = storages[i].label; - break; - } - } - - var onSuccessStorage = function(storage) { - pathsPrefix.externalRootDirectory = 'file://' + storage.fullPath + '/'; - callback(pathsPrefix); - } - - try { - if (label) { - tizen.filesystem.resolve(label, onSuccessStorage, onError); - } else { - callback(pathsPrefix); - } - } catch(error) { - console.error('Failed to resolve external storage: ' + error.message); - callback(pathsPrefix); - } - } - - try { - tizen.filesystem.listStorages(onSuccess, onError); - } catch(error) { - console.error('Failed to list storages: ' + error.message); - callback(pathsPrefix); - } -} - -function setApplicationStorageDirectory(callback) { - var onError = function (error) { - console.error('Failed to get directory: ' + error.message); - callback(pathsPrefix); - }; - - try { - tizen.filesystem.resolve('wgt-package', function(appDir) { - pathsPrefix.applicationDirectory = appDir.toURI() + '/'; - - tizen.filesystem.resolve('wgt-private', function(dataDir) { - pathsPrefix.applicationStorageDirectory = dataDir.toURI() + '/'; - pathsPrefix.dataDirectory = dataDir.toURI() + '/'; - - tizen.filesystem.resolve('wgt-private-tmp', function(cacheDir) { - pathsPrefix.cacheDirectory = cacheDir.toURI() + '/'; - - setExternalStorage(callback); - }, onError, 'r'); - }, onError, 'r'); - }, onError, 'r'); - } catch(error) { - console.error('Failed to get current application: ' + error.message); - callback(pathsPrefix); - } -} - -module.exports = { - requestAllPaths: function(successCallback, errorCallback, args) { - // we ignore errorCallback here, as we're always reporting as much - // information as we currently have - setApplicationStorageDirectory(function(r) { - successCallback && successCallback(r); - }); - } -}; - -//TODO: remove when added to public cordova repository -> begin -}); -//TODO: remove -> end diff --git a/src/file/js/fileSystems-roots.js b/src/file/js/fileSystems-roots.js deleted file mode 100644 index 86229f8..0000000 --- a/src/file/js/fileSystems-roots.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// TODO: remove when added to public cordova repository -> begin -cordova.define('cordova-plugin-file.tizen.fileSystems-roots', function(require, exports, module) { -// TODO: remove -> end - -var channel = require('cordova/channel'); - -channel.waitForInitialization('onGetRootsReady'); -channel.onCordovaReady.subscribe(function() { - rootsUtils.getRoots(function () { - channel.initializationComplete('onGetRootsReady'); - }); -}); - -module.exports = { - requestAllFileSystems: function(successCallback, errorCallback, args) { - rootsUtils.getRoots(successCallback); - } -}; - -//TODO: remove when added to public cordova repository -> begin -}); -//TODO: remove -> end diff --git a/src/file/js/requestFileSystem.js b/src/file/js/requestFileSystem.js deleted file mode 100644 index ba185ca..0000000 --- a/src/file/js/requestFileSystem.js +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// TODO: remove when added to public cordova repository -> begin -cordova.define('cordova-plugin-file.tizen.requestFileSystem', function(require, exports, module) { -// TODO: remove -> end - -module.exports = { - requestFileSystem: function(successCallback, errorCallback, args) { - var type = args[0]; - var size = args[1]; - var fsName; - - switch(type) { - case LocalFileSystem.TEMPORARY: - fsName = 'temporary'; - break; - - case LocalFileSystem.PERSISTENT: - fsName = 'persistent'; - break; - - default: - console.error('Unknown FS type: ' + type); - errorCallback && errorCallback(FileError.TYPE_MISMATCH_ERR); - return; - } - - try { - tizen.systeminfo.getPropertyValue('STORAGE', function (r) { - for (var i = 0; i < r.units.length; ++i) { - // both filesystems are located on internal storage - if ('INTERNAL' === r.units[i].type) { - if (size < r.units[i].availableCapacity) { - rootsUtils.getRoots(function(roots) { - for (var i = 0; i < roots.length; ++i) { - if (fsName === roots[i].filesystemName) { - successCallback({ 'name': fsName, 'root': roots[i] }); - return; - } - } - - console.error('Filesystem not found: ' + fsName); - errorCallback && errorCallback(FileError.NOT_FOUND_ERR); - }); - } else { - console.error('Quote exceeded, requested: ' + size + ', available: ' + r.units[i].availableCapacity); - errorCallback && errorCallback(FileError.QUOTA_EXCEEDED_ERR); - } - return; - } - } - - console.error('Internal storage not found'); - errorCallback && errorCallback(FileError.NOT_FOUND_ERR); - }, function(e) { - console.error('Failed to get storage info: ' + fsName); - errorCallback && errorCallback(FileError.NOT_FOUND_ERR); - } - ); - } catch (e) { - console.error('Exception: ' + e); - errorCallback && errorCallback(FileError.NOT_FOUND_ERR); - } - } -}; - -//TODO: remove when added to public cordova repository -> begin -}); -//TODO: remove -> end diff --git a/src/file/js/resolveLocalFileSystemURI.js b/src/file/js/resolveLocalFileSystemURI.js deleted file mode 100644 index 9dabdc5..0000000 --- a/src/file/js/resolveLocalFileSystemURI.js +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// TODO: remove when added to public cordova repository -> begin -cordova.define('cordova-plugin-file.tizen.resolveLocalFileSystemURI', function(require, exports, module) { -// TODO: remove -> end - -var filePrefix = 'file://'; - -module.exports = { - resolveLocalFileSystemURI: function(successCallback, errorCallback, args) { - var path = rootsUtils.internalUrlToNativePath(args[0]); - - if (!path) { - errorCallback && errorCallback(FileError.ENCODING_ERR); - return; - } - - function onResolve(file) { - var filesystem = rootsUtils.findFilesystem(file.toURI()); - - var entry = rootsUtils.createEntry(file, filesystem.filesystemName); - entry.isDirectory = file.isDirectory; - - successCallback(entry); - } - - function onError(error) { - errorCallback && errorCallback(ConvertTizenFileError(error)); - } - - tizen.filesystem.resolve(path, onResolve, onError, 'r'); - }, - _getLocalFilesystemPath: function(successCallback, errorCallback, args) { - var path = rootsUtils.internalUrlToNativePath(args[0]); - - if (!path) { - errorCallback && errorCallback(FileError.ENCODING_ERR); - } else { - if (0 === path.indexOf(filePrefix)) { - path = path.substring(filePrefix.length); - } - successCallback && successCallback(path); - } - }, -}; - -//TODO: remove when added to public cordova repository -> begin -}); -//TODO: remove -> end diff --git a/src/file/js/rootsUtils.js b/src/file/js/rootsUtils.js deleted file mode 100644 index e673da5..0000000 --- a/src/file/js/rootsUtils.js +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var rootsUtils = (function() { - var filePrefix = 'file:///'; - - function stripTrailingSlash(str) { - if (filePrefix !== str && '/' === str.substr(-1)) { - return str.substr(0, str.length - 1); - } - return str; - } - - function getName(uri) { - return getFullPath(uri).replace(/^.*(\\|\/|\:)/, ''); - } - - function getFullPath(uri) { - var tmp = findFilesystem(uri); - tmp = getNativeUrl(uri).substring(tmp.nativeURL.length); - if (!tmp) { - tmp = '/'; - } - if ('/' !== tmp[0]) { - tmp = '/' + tmp; - } - return tmp; - } - - function getNativeUrl(uri) { - return stripTrailingSlash(uri); - } - - function createEntry(file, fsName) { - var uri = file.toURI(); - return { - name: getName(uri), - fullPath: getFullPath(uri), - nativeURL: encodeURI(getNativeUrl(uri)), - filesystemName: fsName - }; - } - - var roots_to_resolve = [ - { - filesystemName: 'temporary', - name: '', - fullPath: '/', - nativeURL: 'wgt-private-tmp' - }, - { - filesystemName: 'persistent', - name: '', - fullPath: '/', - nativeURL: 'wgt-private' - } - ]; - - var roots = [ - { - filesystemName: 'root', - name: '', - fullPath: '/', - nativeURL: 'file:///' - } - ]; - - var name_to_root; - - function getRoots(successCallback) { - if (roots_to_resolve.length > 0) { - tizen.filesystem.resolve(roots_to_resolve[0].nativeURL, function(dir) { - roots_to_resolve[0].nativeURL = getNativeUrl(dir.toURI()); - roots.push(roots_to_resolve[0]); - roots_to_resolve.splice(0, 1); // remove first item - - // we've resolved one root, check if there are any other - getRoots(successCallback); - }, function(e) { - console.error(e); - // in case of an error, return the roots we have so far - successCallback(roots); - }); - } else { - if (!name_to_root) { - name_to_root = {}; - for (var i = 0; i < roots.length; ++i) { - name_to_root[roots[i].filesystemName] = roots[i]; - } - } - successCallback(roots.slice()); - } - } - - function strncmp(str1, str2, n) { - str1 = str1.substring(0, n); - str2 = str2.substring(0, n); - return ((str1 === str2) ? 0 : ((str1 > str2) ? 1 : -1 )); - } - - function findFilesystem(uri) { - var nativeUrl = getNativeUrl(uri); - for (var i = roots.length - 1; i > 0; --i) { - if (0 === strncmp(nativeUrl, roots[i].nativeURL, roots[i].nativeURL.length)) { - return roots[i]; - } - } - - return roots[0]; // root filesystem - } - - function isRootUri(uri) { - var fs = findFilesystem(uri); - return (fs.nativeURL === getNativeUrl(uri)); - } - - // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#naming-restrictions - var disallowedCharacters = [ '/', '\\', '<', '>', ':', '?', '*', '"', '|' ]; - - function isValidFileName(name) { - for (var i = 0; i < disallowedCharacters.length; ++i) { - if (-1 !== name.indexOf(disallowedCharacters[i])) { - return false; - } - } - - return true; - } - - var localhost = '//localhost/' - var cdvPrefix = 'cdvfile:///'; - - function internalUrlToNativePath(url) { - var input = url; - - // skip parameters - url = url.split('?')[0]; - - // remove localhost - url = url.replace(localhost, '///'); - - if (0 === url.indexOf(cdvPrefix)) { - // cdvfile protocol - url = url.substring(cdvPrefix.length); - - var idx = url.indexOf('/'); - - if (-1 !== idx) { - var fsName = url.substring(0, idx); - var fullPath = url.substring(idx); - url = name_to_root[fsName] ? name_to_root[fsName].nativeURL + fullPath : undefined; - } else { - // malformed URL - url = undefined; - } - } else if (0 === url.indexOf(filePrefix)) { - // check if the filesystem for this URL exists - var found = false; - for (var i = 0; i < roots.length && !found; ++i) { - if (0 === url.indexOf(roots[i].nativeURL)) { - found = true; - } - } - - if (!found) { - url = undefined; - } - } else { - // backwards compatibility, device absolute path - // only TEMPORARY and PERSISTENT paths are allowed - url = filePrefix + url.substring(1); // skip '/' - if (0 !== url.indexOf(name_to_root.temporary.nativeURL) && - 0 !== url.indexOf(name_to_root.persistent.nativeURL)) { - url = undefined; - } - } - - if (url) { - url = decodeURI(getNativeUrl(url)); - } else { - console.error('Failed to decode internal URL: ' + input); - } - - return url; - } - - return { - getRoots: getRoots, - findFilesystem: findFilesystem, - getName: getName, - getFullPath: getFullPath, - getNativeUrl: getNativeUrl, - stripTrailingSlash: stripTrailingSlash, - createEntry: createEntry, - isRootUri: isRootUri, - isValidFileName: isValidFileName, - internalUrlToNativePath: internalUrlToNativePath - }; -})(); diff --git a/src/lib/cordova-5.1.1.js b/src/lib/cordova-5.1.1.js index b6b1965..cb58c1d 100644 --- a/src/lib/cordova-5.1.1.js +++ b/src/lib/cordova-5.1.1.js @@ -1334,8 +1334,6 @@ module.exports = { modulemapper.clobbers('cordova/exec/proxy', 'cordova.commandProxy'); - tizen.cordova.load(require); - channel.onNativeReady.fire(); // End of bootstrap diff --git a/src/lib/cordova_plugins.js b/src/lib/cordova_plugins.js index 443c37f..00817ca 100644 --- a/src/lib/cordova_plugins.js +++ b/src/lib/cordova_plugins.js @@ -205,6 +205,73 @@ module.exports = [ ], "runs": true }, + { + "file": "plugins/cordova-plugin-file/tizen/Errors.js", + "id": "cordova-plugin-file.tizen.Errors", + "runs": true + }, + { + "file": "plugins/cordova-plugin-file/tizen/rootUtils.js", + "id": "cordova-plugin-file.tizen.rootUtils", + "runs": true + }, + { + "file": "plugins/cordova-plugin-file/tizen/DirectoryEntry.js", + "id": "cordova-plugin-file.tizen.DirectoryEntry", + "runs": true + }, + { + "file": "plugins/cordova-plugin-file/tizen/DirectoryReader.js", + "id": "cordova-plugin-file.tizen.DirectoryReader", + "runs": true + }, + { + "file": "plugins/cordova-plugin-file/tizen/Entry.js", + "id": "cordova-plugin-file.tizen.Entry", + "runs": true + }, + { + "file": "plugins/cordova-plugin-file/tizen/FileReader.js", + "id": "cordova-plugin-file.tizen.FileReader", + "runs": true + }, + { + "file": "plugins/cordova-plugin-file/tizen/fileSystemPaths.js", + "id": "cordova-plugin-file.tizen.fileSystemPaths", + "runs": true + }, + { + "file": "plugins/cordova-plugin-file/tizen/fileSystems-roots.js", + "id": "cordova-plugin-file.tizen.fileSystems-roots", + "runs": true + }, + { + "file": "plugins/cordova-plugin-file/tizen/FileWriter.js", + "id": "cordova-plugin-file.tizen.FileWriter", + "runs": true + }, + { + "file": "plugins/cordova-plugin-file/tizen/requestFileSystem.js", + "id": "cordova-plugin-file.tizen.requestFileSystem", + "runs": true + }, + { + "file": "plugins/cordova-plugin-file/tizen/resolveLocalFileSystemURI.js", + "id": "cordova-plugin-file.tizen.resolveLocalFileSystemURI", + "runs": true + }, + { + "file": "plugins/cordova-plugin-file/tizen/File.js", + "id": "cordova-plugin-file.tizen.File", + "runs": true + }, + { + "file": "plugins/cordova-plugin-file/tizen/FileSystem.js", + "id": "cordova-plugin-file.tizen.FileSystem", + "merges": [ + "window.FileSystem" + ] + }, { "file": "plugins/cordova-plugin-file-transfer/www/FileTransferError.js", "id": "cordova-plugin-file-transfer.FileTransferError", diff --git a/src/lib/plugins/cordova-plugin-file/tizen/DirectoryEntry.js b/src/lib/plugins/cordova-plugin-file/tizen/DirectoryEntry.js new file mode 100644 index 0000000..4349e33 --- /dev/null +++ b/src/lib/plugins/cordova-plugin-file/tizen/DirectoryEntry.js @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO: remove when added to public cordova repository -> begin +cordova.define('cordova-plugin-file.tizen.DirectoryEntry', function(require, exports, module) { +// TODO: remove -> end + + var convertTizenFileError = require('cordova-plugin-file.tizen.Errors'); + var rootUtils = require('cordova-plugin-file.tizen.rootUtils'); + + function sanitizePath(path) { + var prepend = '/' === path[0]; + var input = path.split('/'); + var output = []; + + for (var i = 0; i < input.length; ++i) { + var part = input[i]; + switch (part) { + case '': + case '.': + // ignore + break; + + case '..': + // remove previous part + output.pop(); + break; + + default: + output.push(part); + break; + } + } + + return (prepend ? '/' : '') + output.join('/'); + } + + var getFunction = function(successCallback, errorCallback, args, isDirectory) { + var uri = rootUtils.internalUrlToNativePath(args[0]), + path = rootUtils.stripTrailingSlash(args[1]), + options = args[2] || {}, + create_flag = !!options.create, + exclusive_flag = !!options.exclusive, + absolute_path = ''; + + if (!uri) { + errorCallback && errorCallback(FileError.ENCODING_ERR); + return; + } + + if ('/' === path[0]) { + // path seems absolute, checking if path is a child of this object URI + if (0 === path.indexOf(uri)) { + // path is child - OK + absolute_path = path; + } else { + // path is not a child - calling error callback + console.error('Error - path is not a child of current directory entry') + errorCallback && errorCallback(FileError.INVALID_STATE_ERR); + return; + } + } else { + // path seems to be relative path, combining absolute path + absolute_path = uri + '/' + path; + } + + var root = rootUtils.findFilesystem(absolute_path).nativeURL; + var clean_path = sanitizePath(absolute_path); + + if (0 !== clean_path.indexOf(root)) { + // we went above the root directory, force the absolute path to be + // at least in that directory + clean_path = root + '/' + sanitizePath(absolute_path.substring(root.length + 1)); + } + + var parent_path = clean_path.substring(0, clean_path.lastIndexOf('/')); + var child_name = clean_path.substring(clean_path.lastIndexOf('/') + 1); + + if (!rootUtils.isValidFileName(child_name)) { + console.error('Disallowed character detected in file name: ' + child_name); + errorCallback && errorCallback(FileError.ENCODING_ERR); + return; + } + + var resolveSuccess = function(dir) { + // clean_path points to existing destination + if (create_flag && exclusive_flag) { + console.error('Error while resolving dir - already exist dir'); + errorCallback && errorCallback(FileError.PATH_EXISTS_ERR); + } else if (!create_flag && dir.isDirectory !== isDirectory) { + console.error('Error while resolving dir - already exist file'); + errorCallback && errorCallback(FileError.TYPE_MISMATCH_ERR); + } else { + successCallback && successCallback(rootUtils.createEntry(dir)); + } + }; + + var resolveError = function(e) { + if (create_flag) { + // should create directory + try { + // resolve parent + tizen.filesystem.resolve(parent_path, + function(dir) { + // create object + var new_obj; + if (isDirectory) { + new_obj = dir.createDirectory(child_name); + } else { + new_obj = dir.createFile(child_name); + } + + successCallback && successCallback(rootUtils.createEntry(new_obj)); + }, + function () { + console.error('Error - immediate parent does not exist'); + errorCallback && errorCallback(FileError.INVALID_STATE_ERR); + }, + 'rw' + ); + } catch (err) { + console.error('Error - Could not resolve'); + errorCallback && errorCallback(convertTizenFileError(err)); + } + } else { + console.error('Error - create flag is false - new directory would not be created'); + errorCallback && errorCallback(FileError.NOT_FOUND_ERR); + } + }; + + // try to resolve + try { + tizen.filesystem.resolve(clean_path, resolveSuccess, resolveError, 'rw'); + } catch (err) { + console.error('Error - Could not resolve'); + errorCallback && errorCallback(convertTizenFileError(err)); + } + }; + +module.exports = { + getDirectory: function(successCallback, errorCallback, args) { + getFunction(successCallback, errorCallback, args, true); + }, + removeRecursively: function(successCallback, errorCallback, args) { + var uri = rootUtils.internalUrlToNativePath(args[0]); + + if (!uri) { + errorCallback && errorCallback(FileError.ENCODING_ERR); + return; + } + + if (rootUtils.isRootUri(uri)) { + console.error('It is not allowed to remove root directory.'); + errorCallback && errorCallback(FileError.NO_MODIFICATION_ALLOWED_ERR); + return; + } + + // resolve parent + var tmp_path = uri[uri.length-1] === '/' ? uri.substring(0, uri.lastIndexOf('/')) : uri; + var parent_path = tmp_path.substring(0, tmp_path.lastIndexOf('/')+1); + try { + tizen.filesystem.resolve( + parent_path, + function(dir) { + try { + if (dir.isDirectory) { + dir.deleteDirectory( + uri, + true, + function() { + successCallback && successCallback(); + }, function(e) { + console.error('Error - recursively deletion failed'); + errorCallback && errorCallback(FileError.NO_MODIFICATION_ALLOWED_ERR); + }); + } else { + console.error('Error - entry is not a directory'); + errorCallback && errorCallback(FileError.INVALID_STATE_ERR); + } + } catch (err) { + console.error('Error - Could not deleteDirectory'); + errorCallback && errorCallback(convertTizenFileError(err)); + } + }, function(e) { + console.error('Error: ' + e.message); + errorCallback && errorCallback(convertTizenFileError(e)); + }, 'rw' + ); + } catch (err) { + console.error('Error - Could not resolve'); + errorCallback && errorCallback(convertTizenFileError(err)); + } + }, + getFile: function(successCallback, errorCallback, args) { + getFunction(successCallback, errorCallback, args, false); + } +}; + +//TODO: remove when added to public cordova repository -> begin +}); +//TODO: remove -> end diff --git a/src/lib/plugins/cordova-plugin-file/tizen/DirectoryReader.js b/src/lib/plugins/cordova-plugin-file/tizen/DirectoryReader.js new file mode 100644 index 0000000..4d864ff --- /dev/null +++ b/src/lib/plugins/cordova-plugin-file/tizen/DirectoryReader.js @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO: remove when added to public cordova repository -> begin +cordova.define('cordova-plugin-file.tizen.DirectoryReader', function(require, exports, module) { +// TODO: remove -> end + +var convertTizenFileError = require('cordova-plugin-file.tizen.Errors'); +var rootUtils = require('cordova-plugin-file.tizen.rootUtils'); + +module.exports = { + readEntries: function(successCallback, errorCallback, args) { + var uri = rootUtils.internalUrlToNativePath(args[0]); + + if (!uri) { + errorCallback && errorCallback(FileError.ENCODING_ERR); + return; + } + + var fail = function(e) { + errorCallback && errorCallback(convertTizenFileError(e)); + } + try { + tizen.filesystem.resolve(uri, + function (f) { + f.listFiles(function(v) { + var retVal = []; + for (var i = 0; i < v.length; ++i) { + var obj = rootUtils.createEntry(v[i], rootUtils.findFilesystem(v[i].toURI()).filesystemName); + obj.isDirectory = v[i].isDirectory; + obj.isFile = v[i].isFile; + retVal.push(obj); + }; + successCallback(retVal); + }, fail); + }, fail, 'r'); + } catch (e) { + fail(e); + } + } +}; + +//TODO: remove when added to public cordova repository -> begin +}); +//TODO: remove -> end diff --git a/src/lib/plugins/cordova-plugin-file/tizen/Entry.js b/src/lib/plugins/cordova-plugin-file/tizen/Entry.js new file mode 100644 index 0000000..a677fea --- /dev/null +++ b/src/lib/plugins/cordova-plugin-file/tizen/Entry.js @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO: remove when added to public cordova repository -> begin +cordova.define('cordova-plugin-file.tizen.Entry', function(require, exports, module) { +// TODO: remove -> end + +var convertTizenFileError = require('cordova-plugin-file.tizen.Errors'); +var rootUtils = require('cordova-plugin-file.tizen.rootUtils'); + +var resolveParent = function(srcURL, errorCallback, rest){ + try { + tizen.filesystem.resolve( + srcURL, + function (srcFile) { + var parentDir = srcFile.parent; + if (!parentDir) { + console.error('Error - could not resolve file ' + srcURL); + errorCallback && errorCallback(FileError.ENCODING_ERR); + } else { + rest(srcFile, parentDir); + } + }, function (err) { + console.error('Error - resolve file ' + srcURL + ' failed'); + errorCallback && errorCallback(convertTizenFileError(err)); + }, + 'r'); + } catch (exception) { + console.error('Error - resolve ' + srcURL + ' file thrown exception'); + errorCallback && errorCallback(convertTizenFileError(exception)); + } +}; + +var changeFile = function(method, successCallback, errorCallback, args) { + var srcURL = rootUtils.internalUrlToNativePath(args[0]); + var name = args[2]; + var destDir = rootUtils.internalUrlToNativePath(args[1]); + var destURL = destDir + '/' + name; + + function fail(e, msg) { + console.error(msg); + if (errorCallback) { + errorCallback(e); + } + } + + if (!srcURL || !destDir) { + fail(FileError.ENCODING_ERR, 'Error - Failed to decode internal URL.'); + return; + } + + if (!rootUtils.isValidFileName(name)) { + fail(FileError.ENCODING_ERR, 'Error - Disallowed character detected in the file name: ' + name); + return; + } + + if (-1 !== (destURL + '/').indexOf(srcURL + '/')) { + fail(FileError.INVALID_MODIFICATION_ERR, 'Error - Cannot copy/move onto itself.'); + return; + } + + function performAction(srcFile, parentDir) { + try { + parentDir[method](srcFile.fullPath, + destURL, + true, + function () { + try { + tizen.filesystem.resolve( + destURL, + function (destFile) { + var destEntry = rootUtils.createEntry(destFile); + destEntry.isDirectory = destFile.isDirectory; + successCallback && successCallback(destEntry); + }, function (err) { + fail(convertTizenFileError(err), 'Error - resolve result entry failed'); + } + ); + } catch (exception) { + fail(convertTizenFileError(exception), 'Error - resolve result entry thrown exception'); + } + }, function (err) { + fail(convertTizenFileError(err), 'Error - ' + method + ' operation failed'); + } + ); + } catch (exception) { + fail(convertTizenFileError(exception), 'Error - ' + method + ' operation thrown exception'); + } + } + + try { + tizen.filesystem.resolve(destDir, function(d) { + resolveParent (srcURL, errorCallback, + function(srcFile, parentDir) { + try { + // check if destination entry exists + tizen.filesystem.resolve(destURL, function(d) { + // destination exists, we may proceed only if it's the same type + // as source + if (d.isFile === srcFile.isFile && d.isDirectory === srcFile.isDirectory) { + performAction(srcFile, parentDir); + } else { + fail(FileError.INVALID_MODIFICATION_ERR, 'Error - source and destination have mismatched types'); + } + }, function() { + // error means that we're safe to proceed + performAction(srcFile, parentDir); + }, 'r'); + } catch (exception) { + fail(convertTizenFileError(exception), 'Error - resolve destination entry threw exception'); + } + } + ); + }, function() { + fail(FileError.NOT_FOUND_ERR, 'Error - destination directory does not exist'); + }, 'r'); + } catch (e) { + fail(convertTizenFileError(e), 'Error - resolve destination directory threw exception'); + } +}; + +module.exports = { + getFileMetadata: function(successCallback, errorCallback, args) { + var uri = rootUtils.internalUrlToNativePath(args[0]); + if (!uri) { + errorCallback && errorCallback(FileError.ENCODING_ERR); + return; + } + try { + tizen.filesystem.resolve(uri, function (file) { + var result = { 'size': file.fileSize, 'lastModifiedDate': file.modified }; + successCallback && successCallback(result); + }, function (err) { + errorCallback && errorCallback(convertTizenFileError(err)); + }, 'r'); + } catch (exception) { + console.error('Error - resolve failed'); + errorCallback && errorCallback(convertTizenFileError(exception)); + } + }, + setMetadata: function(successCallback, errorCallback, args) { + console.error('setMetadata - Not supported'); + errorCallback && errorCallback(FileError.ENCODING_ERR); + }, + moveTo: function(successCallback, errorCallback, args) { + changeFile('moveTo', successCallback, errorCallback, args); + }, + copyTo: function(successCallback, errorCallback, args) { + changeFile('copyTo', successCallback, errorCallback, args); + }, + remove: function(successCallback, errorCallback, args) { + var url = rootUtils.internalUrlToNativePath(args[0]); + + if (!url) { + errorCallback && errorCallback(FileError.ENCODING_ERR); + return; + } + + if (rootUtils.isRootUri(url)) { + console.error('It is not allowed to remove root directory.'); + errorCallback && errorCallback(FileError.NO_MODIFICATION_ALLOWED_ERR); + return; + } + + resolveParent(url, errorCallback, + function(srcFile, parentDir){ + var method = srcFile.isFile ? 'deleteFile' : 'deleteDirectory'; + var args = [srcFile.fullPath, + false, + function() {successCallback && successCallback();}, + function(err) { + console.error('Error - ' + method + ' failed'); + errorCallback && errorCallback(convertTizenFileError(err)); + }]; + if (srcFile.isFile) { + //remove recursive flag + args.splice(1, 1); + } + try { + parentDir[method].apply(parentDir, args); + } catch (exception) { + console.error('Error - ' + method + ' thrown exception ' + JSON.stringify(exception)); + errorCallback && errorCallback(convertTizenFileError(exception)); + } + } + ); + }, + getParent: function(successCallback, errorCallback, args) { + var url = rootUtils.internalUrlToNativePath(args[0]); + + if (!url) { + errorCallback && errorCallback(FileError.ENCODING_ERR); + return; + } + + if (rootUtils.isRootUri(url)) { + successCallback && successCallback(rootUtils.findFilesystem(url)); + return; + } + + resolveParent(url, errorCallback, + function(srcFile, parentDir){ + successCallback && successCallback(rootUtils.createEntry(srcFile.parent)); + } + ); + } +}; + +//TODO: remove when added to public cordova repository -> begin +}); +//TODO: remove -> end diff --git a/src/lib/plugins/cordova-plugin-file/tizen/Errors.js b/src/lib/plugins/cordova-plugin-file/tizen/Errors.js new file mode 100644 index 0000000..c31ff4c --- /dev/null +++ b/src/lib/plugins/cordova-plugin-file/tizen/Errors.js @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO: remove when added to public cordova repository -> begin +cordova.define('cordova-plugin-file.tizen.Errors', function(require, exports, module) { +// TODO: remove -> end + +/** + * Function converting a Tizen error to a cordova error + * + * {unsigned short} WebAPIError error + */ +function convertTizenFileError(err) { + switch (err.name) { + case 'InvalidValuesError': + return FileError.ENCODING_ERR; + + case 'NotFoundError': + return FileError.NOT_FOUND_ERR; + + case 'IOError': + return FileError.INVALID_MODIFICATION_ERR; + + default: + return FileError.ENCODING_ERR; + } +} + +module.exports = convertTizenFileError; + +//TODO: remove when added to public cordova repository -> begin +}); +//TODO: remove -> end diff --git a/src/lib/plugins/cordova-plugin-file/tizen/File.js b/src/lib/plugins/cordova-plugin-file/tizen/File.js new file mode 100644 index 0000000..35c2f6b --- /dev/null +++ b/src/lib/plugins/cordova-plugin-file/tizen/File.js @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO: remove when added to public cordova repository -> begin +var plugin_name = 'cordova-plugin-file.tizen.File'; + +cordova.define(plugin_name, function(require, exports, module) { +// TODO: remove -> end + +var modules = [ + 'DirectoryEntry', + 'DirectoryReader', + 'Entry', + 'FileReader', + 'fileSystemPaths', + 'fileSystems-roots', + 'FileWriter', + 'requestFileSystem', + 'resolveLocalFileSystemURI' +]; + +// merge methods from submodules into this one +for (var i = 0; i < modules.length; ++i) { + var m = require('cordova-plugin-file.tizen.' + modules[i]); + for (var prop in m) { + if (m.hasOwnProperty(prop)) { + exports[prop] = m[prop]; + } + } +} + +require("cordova/exec/proxy").add("File", exports); + +console.log('Loaded cordova.file API'); + +// TODO: remove when added to public cordova repository -> begin +}); +// TODO: remove -> end diff --git a/src/lib/plugins/cordova-plugin-file/tizen/FileReader.js b/src/lib/plugins/cordova-plugin-file/tizen/FileReader.js new file mode 100644 index 0000000..b6c321c --- /dev/null +++ b/src/lib/plugins/cordova-plugin-file/tizen/FileReader.js @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO: remove when added to public cordova repository -> begin +cordova.define('cordova-plugin-file.tizen.FileReader', function(require, exports, module) { +// TODO: remove -> end + +var convertTizenFileError = require('cordova-plugin-file.tizen.Errors'); +var rootUtils = require('cordova-plugin-file.tizen.rootUtils'); + +function read(operation, url, start, end, successCallback, errorCallback, encoding) { + url = rootUtils.internalUrlToNativePath(url); + + if (!url) { + errorCallback && errorCallback(FileError.ENCODING_ERR); + return; + } + + var fail = function(e) { + errorCallback && errorCallback(convertTizenFileError(e)); + } + var win = function(size) { + successCallback && successCallback(size); + } + try { + tizen.filesystem.resolve(url, function(file) { + if (0 === end - start) { + // nothing to read, report success + win(); + } else { + try { + file.openStream('r', function(stream) { + try { + stream.position = start; + var r = stream[operation](end - start); + stream.close(); + win(r); + } catch (e) { + fail(e); + } + }, fail, encoding); + } catch (e) { + fail(e); + } + } + }, fail, 'r'); + } catch (e) { + fail(e); + } +} + +module.exports = { + readAsText: function(successCallback, errorCallback, args) { + read('read', args[0], args[2], args[3], function(r) { + successCallback && successCallback(r || ''); + }, errorCallback, args[1]); + }, + readAsDataURL: function(successCallback, errorCallback, args) { + read('readBase64', args[0], args[1], args[2], function(r) { + r = 'data:;base64,' + (r || ''); // MIME is missing because it's not passed to exec() + successCallback && successCallback(r); + }, errorCallback); + }, + readAsBinaryString: function(successCallback, errorCallback, args) { + read('readBytes', args[0], args[1], args[2], function(r) { + r = r || []; + var str = ''; + // this may be not so efficient, but + // String.fromCharCode.apply(null, r); + // may throw if r.length is large enough + for (var i = 0; i < r.length; ++i) { + str += String.fromCharCode(r[i]); + } + successCallback && successCallback(str); + }, errorCallback); + }, + readAsArrayBuffer: function(successCallback, errorCallback, args) { + read('readBytes', args[0], args[1], args[2], function(r) { + successCallback && successCallback(r || []); + }, errorCallback); + }, +}; + +//TODO: remove when added to public cordova repository -> begin +}); +//TODO: remove -> end diff --git a/src/lib/plugins/cordova-plugin-file/tizen/FileSystem.js b/src/lib/plugins/cordova-plugin-file/tizen/FileSystem.js new file mode 100644 index 0000000..8eacf99 --- /dev/null +++ b/src/lib/plugins/cordova-plugin-file/tizen/FileSystem.js @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO: remove when added to public cordova repository -> begin +cordova.define('cordova-plugin-file.tizen.FileSystem', function(require, exports, module) { +// TODO: remove -> end + +module.exports = { + __format__: function(fullPath) { + return 'cdvfile://localhost/' + this.name + fullPath; + } +}; + +console.log('Loaded cordova.file FileSystem'); + +// TODO: remove when added to public cordova repository -> begin +}); +// TODO: remove -> end diff --git a/src/lib/plugins/cordova-plugin-file/tizen/FileWriter.js b/src/lib/plugins/cordova-plugin-file/tizen/FileWriter.js new file mode 100644 index 0000000..e592166 --- /dev/null +++ b/src/lib/plugins/cordova-plugin-file/tizen/FileWriter.js @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO: remove when added to public cordova repository -> begin +cordova.define('cordova-plugin-file.tizen.FileWriter', function(require, exports, module) { +// TODO: remove -> end + +var convertTizenFileError = require('cordova-plugin-file.tizen.Errors'); +var rootUtils = require('cordova-plugin-file.tizen.rootUtils'); + +// https://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array +function toUTF8Array(str) { + var utf8 = []; + for (var i = 0; i < str.length; ++i) { + var charcode = str.charCodeAt(i); + if (charcode < 0x80) utf8.push(charcode); + else if (charcode < 0x800) { + utf8.push(0xc0 | (charcode >> 6), + 0x80 | (charcode & 0x3f)); + } + else if (charcode < 0xd800 || charcode >= 0xe000) { + utf8.push(0xe0 | (charcode >> 12), + 0x80 | ((charcode>>6) & 0x3f), + 0x80 | (charcode & 0x3f)); + } + // surrogate pair + else { + i++; + // UTF-16 encodes 0x10000-0x10FFFF by + // subtracting 0x10000 and splitting the + // 20 bits of 0x0-0xFFFFF into two halves + charcode = 0x10000 + (((charcode & 0x3ff)<<10) + | (str.charCodeAt(i) & 0x3ff)); + utf8.push(0xf0 | (charcode >>18), + 0x80 | ((charcode>>12) & 0x3f), + 0x80 | ((charcode>>6) & 0x3f), + 0x80 | (charcode & 0x3f)); + } + } + return utf8; +} + +module.exports = { + write: function(successCallback, errorCallback, args) { + var uri = rootUtils.internalUrlToNativePath(args[0]); + var data = args[1]; + var position = args[2]; + var isBinary = args[3]; + + if (!uri) { + errorCallback && errorCallback(FileError.ENCODING_ERR); + return; + } + + if (!isBinary) { + if ('string' === typeof data) { + // convert to UTF-8, as this is the default encoding for read operations + data = toUTF8Array(data); + } else { + // we don't support other types + errorCallback && errorCallback(FileError.TYPE_MISMATCH_ERR); + return; + } + } else { + if (data instanceof ArrayBuffer) { + var a = new Uint8Array(data); + data = []; + for (var i = 0; i < a.length; ++i) { + data.push(a[i]); + } + } else { + // we don't support other types + errorCallback && errorCallback(FileError.TYPE_MISMATCH_ERR); + return; + } + } + + var onSuccess = function (file) { + if (file.isDirectory) { + errorCallback && errorCallback(FileError.INVALID_MODIFICATION_ERR); + return; + } + + var openStreamSuccess = function (stream) { + try { + stream.position = position; + stream.writeBytes(data); + var length = stream.position - position; + stream.close(); + + // The cordova documentation points to: http://dev.w3.org/2009/dap/file-system/file-writer.html + // This spec states that file length after write operation should be the greater of + // (pre-write length) and (pre-write position + data.size), however + // the cordova implementation sets it to the latter. In order to accommodate + // for this, we need to truncate after write... + module.exports.truncate(function() { + successCallback && successCallback(length); + }, errorCallback, [args[0], stream.position]); + } catch (error) { + errorCallback && errorCallback(convertTizenFileError(error)); + } + } + + var openStreamError = function (error) { + errorCallback && errorCallback(convertTizenFileError(error)); + } + + try { + file.openStream('rw', openStreamSuccess, openStreamError); + } catch (error) { + errorCallback && errorCallback(convertTizenFileError(error)); + } + } + + var onError = function (error) { + errorCallback && errorCallback(convertTizenFileError(error)); + } + + try { + tizen.filesystem.resolve(uri, onSuccess, onError, 'rw'); + } catch (error) { + errorCallback && errorCallback(convertTizenFileError(error)); + } + }, + + truncate: function(successCallback, errorCallback, args) { + var uri = rootUtils.internalUrlToNativePath(args[0]); + var length = args[1]; + + if (!uri) { + errorCallback && errorCallback(FileError.ENCODING_ERR); + return; + } + + var uriPrefix = 'file://'; + if (0 === uri.indexOf(uriPrefix)) { + uri = uri.substring(uriPrefix.length); + } + + tizen.cordova.file.truncate(uri, length, successCallback, function(error) { + if (errorCallback) { + errorCallback(convertTizenFileError(error)); + } + }); + } +}; + +//TODO: remove when added to public cordova repository -> begin +}); +//TODO: remove -> end diff --git a/src/lib/plugins/cordova-plugin-file/tizen/fileSystemPaths.js b/src/lib/plugins/cordova-plugin-file/tizen/fileSystemPaths.js new file mode 100644 index 0000000..ec1bb69 --- /dev/null +++ b/src/lib/plugins/cordova-plugin-file/tizen/fileSystemPaths.js @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO: remove when added to public cordova repository -> begin +cordova.define('cordova-plugin-file.tizen.fileSystemPaths', function(require, exports, module) { +// TODO: remove -> end + +var pathsPrefix = { + sharedDirectory: 'file:///opt/usr/media/' +}; + +function setExternalStorage(callback) { + var label = ''; + + var onError = function(error) { + console.error('Failed to get external storage: ' + error.message); + callback(pathsPrefix); + } + + var onSuccess = function(storages) { + for (var i = 0; i < storages.length; ++i) { + if (storages[i].type === 'EXTERNAL' && storages[i].state === 'MOUNTED') { + label = storages[i].label; + break; + } + } + + var onSuccessStorage = function(storage) { + pathsPrefix.externalRootDirectory = 'file://' + storage.fullPath + '/'; + callback(pathsPrefix); + } + + try { + if (label) { + tizen.filesystem.resolve(label, onSuccessStorage, onError); + } else { + callback(pathsPrefix); + } + } catch(error) { + console.error('Failed to resolve external storage: ' + error.message); + callback(pathsPrefix); + } + } + + try { + tizen.filesystem.listStorages(onSuccess, onError); + } catch(error) { + console.error('Failed to list storages: ' + error.message); + callback(pathsPrefix); + } +} + +function setApplicationStorageDirectory(callback) { + var onError = function (error) { + console.error('Failed to get directory: ' + error.message); + callback(pathsPrefix); + }; + + try { + tizen.filesystem.resolve('wgt-package', function(appDir) { + pathsPrefix.applicationDirectory = appDir.toURI() + '/'; + + tizen.filesystem.resolve('wgt-private', function(dataDir) { + pathsPrefix.applicationStorageDirectory = dataDir.toURI() + '/'; + pathsPrefix.dataDirectory = dataDir.toURI() + '/'; + + tizen.filesystem.resolve('wgt-private-tmp', function(cacheDir) { + pathsPrefix.cacheDirectory = cacheDir.toURI() + '/'; + + setExternalStorage(callback); + }, onError, 'r'); + }, onError, 'r'); + }, onError, 'r'); + } catch(error) { + console.error('Failed to get current application: ' + error.message); + callback(pathsPrefix); + } +} + +module.exports = { + requestAllPaths: function(successCallback, errorCallback, args) { + // we ignore errorCallback here, as we're always reporting as much + // information as we currently have + setApplicationStorageDirectory(function(r) { + successCallback && successCallback(r); + }); + } +}; + +//TODO: remove when added to public cordova repository -> begin +}); +//TODO: remove -> end diff --git a/src/lib/plugins/cordova-plugin-file/tizen/fileSystems-roots.js b/src/lib/plugins/cordova-plugin-file/tizen/fileSystems-roots.js new file mode 100644 index 0000000..af983b7 --- /dev/null +++ b/src/lib/plugins/cordova-plugin-file/tizen/fileSystems-roots.js @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO: remove when added to public cordova repository -> begin +cordova.define('cordova-plugin-file.tizen.fileSystems-roots', function(require, exports, module) { +// TODO: remove -> end + +var rootUtils = require('cordova-plugin-file.tizen.rootUtils'); + +var channel = require('cordova/channel'); + +channel.waitForInitialization('onGetRootsReady'); +channel.onCordovaReady.subscribe(function() { + rootUtils.getRoots(function () { + channel.initializationComplete('onGetRootsReady'); + }); +}); + +module.exports = { + requestAllFileSystems: function(successCallback, errorCallback, args) { + rootUtils.getRoots(successCallback); + } +}; + +//TODO: remove when added to public cordova repository -> begin +}); +//TODO: remove -> end diff --git a/src/lib/plugins/cordova-plugin-file/tizen/requestFileSystem.js b/src/lib/plugins/cordova-plugin-file/tizen/requestFileSystem.js new file mode 100644 index 0000000..ddd3f10 --- /dev/null +++ b/src/lib/plugins/cordova-plugin-file/tizen/requestFileSystem.js @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO: remove when added to public cordova repository -> begin +cordova.define('cordova-plugin-file.tizen.requestFileSystem', function(require, exports, module) { +// TODO: remove -> end + +var rootUtils = require('cordova-plugin-file.tizen.rootUtils'); + +module.exports = { + requestFileSystem: function(successCallback, errorCallback, args) { + var type = args[0]; + var size = args[1]; + var fsName; + + switch(type) { + case LocalFileSystem.TEMPORARY: + fsName = 'temporary'; + break; + + case LocalFileSystem.PERSISTENT: + fsName = 'persistent'; + break; + + default: + console.error('Unknown FS type: ' + type); + errorCallback && errorCallback(FileError.TYPE_MISMATCH_ERR); + return; + } + + try { + tizen.systeminfo.getPropertyValue('STORAGE', function (r) { + for (var i = 0; i < r.units.length; ++i) { + // both filesystems are located on internal storage + if ('INTERNAL' === r.units[i].type) { + if (size < r.units[i].availableCapacity) { + rootUtils.getRoots(function(roots) { + for (var i = 0; i < roots.length; ++i) { + if (fsName === roots[i].filesystemName) { + successCallback({ 'name': fsName, 'root': roots[i] }); + return; + } + } + + console.error('Filesystem not found: ' + fsName); + errorCallback && errorCallback(FileError.NOT_FOUND_ERR); + }); + } else { + console.error('Quote exceeded, requested: ' + size + ', available: ' + r.units[i].availableCapacity); + errorCallback && errorCallback(FileError.QUOTA_EXCEEDED_ERR); + } + return; + } + } + + console.error('Internal storage not found'); + errorCallback && errorCallback(FileError.NOT_FOUND_ERR); + }, function(e) { + console.error('Failed to get storage info: ' + fsName); + errorCallback && errorCallback(FileError.NOT_FOUND_ERR); + } + ); + } catch (e) { + console.error('Exception: ' + e); + errorCallback && errorCallback(FileError.NOT_FOUND_ERR); + } + } +}; + +//TODO: remove when added to public cordova repository -> begin +}); +//TODO: remove -> end diff --git a/src/lib/plugins/cordova-plugin-file/tizen/resolveLocalFileSystemURI.js b/src/lib/plugins/cordova-plugin-file/tizen/resolveLocalFileSystemURI.js new file mode 100644 index 0000000..8ad212d --- /dev/null +++ b/src/lib/plugins/cordova-plugin-file/tizen/resolveLocalFileSystemURI.js @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO: remove when added to public cordova repository -> begin +cordova.define('cordova-plugin-file.tizen.resolveLocalFileSystemURI', function(require, exports, module) { +// TODO: remove -> end + +var convertTizenFileError = require('cordova-plugin-file.tizen.Errors'); +var rootUtils = require('cordova-plugin-file.tizen.rootUtils'); + +var filePrefix = 'file://'; + +module.exports = { + resolveLocalFileSystemURI: function(successCallback, errorCallback, args) { + var path = rootUtils.internalUrlToNativePath(args[0]); + + if (!path) { + errorCallback && errorCallback(FileError.ENCODING_ERR); + return; + } + + function onResolve(file) { + var filesystem = rootUtils.findFilesystem(file.toURI()); + + var entry = rootUtils.createEntry(file, filesystem.filesystemName); + entry.isDirectory = file.isDirectory; + + successCallback(entry); + } + + function onError(error) { + errorCallback && errorCallback(convertTizenFileError(error)); + } + + tizen.filesystem.resolve(path, onResolve, onError, 'r'); + }, + _getLocalFilesystemPath: function(successCallback, errorCallback, args) { + var path = rootUtils.internalUrlToNativePath(args[0]); + + if (!path) { + errorCallback && errorCallback(FileError.ENCODING_ERR); + } else { + if (0 === path.indexOf(filePrefix)) { + path = path.substring(filePrefix.length); + } + successCallback && successCallback(path); + } + }, +}; + +//TODO: remove when added to public cordova repository -> begin +}); +//TODO: remove -> end diff --git a/src/lib/plugins/cordova-plugin-file/tizen/rootUtils.js b/src/lib/plugins/cordova-plugin-file/tizen/rootUtils.js new file mode 100644 index 0000000..294ee61 --- /dev/null +++ b/src/lib/plugins/cordova-plugin-file/tizen/rootUtils.js @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO: remove when added to public cordova repository -> begin +cordova.define('cordova-plugin-file.tizen.rootUtils', function(require, exports, module) { +// TODO: remove -> end + +var rootUtils = (function() { + var filePrefix = 'file:///'; + + function stripTrailingSlash(str) { + if (filePrefix !== str && '/' === str.substr(-1)) { + return str.substr(0, str.length - 1); + } + return str; + } + + function getName(uri) { + return getFullPath(uri).replace(/^.*(\\|\/|\:)/, ''); + } + + function getFullPath(uri) { + var tmp = findFilesystem(uri); + tmp = getNativeUrl(uri).substring(tmp.nativeURL.length); + if (!tmp) { + tmp = '/'; + } + if ('/' !== tmp[0]) { + tmp = '/' + tmp; + } + return tmp; + } + + function getNativeUrl(uri) { + return stripTrailingSlash(uri); + } + + function createEntry(file, fsName) { + var uri = file.toURI(); + return { + name: getName(uri), + fullPath: getFullPath(uri), + nativeURL: encodeURI(getNativeUrl(uri)), + filesystemName: fsName + }; + } + + var roots_to_resolve = [ + { + filesystemName: 'temporary', + name: '', + fullPath: '/', + nativeURL: 'wgt-private-tmp' + }, + { + filesystemName: 'persistent', + name: '', + fullPath: '/', + nativeURL: 'wgt-private' + } + ]; + + var roots = [ + { + filesystemName: 'root', + name: '', + fullPath: '/', + nativeURL: 'file:///' + } + ]; + + var name_to_root; + + function getRoots(successCallback) { + if (roots_to_resolve.length > 0) { + tizen.filesystem.resolve(roots_to_resolve[0].nativeURL, function(dir) { + roots_to_resolve[0].nativeURL = getNativeUrl(dir.toURI()); + roots.push(roots_to_resolve[0]); + roots_to_resolve.splice(0, 1); // remove first item + + // we've resolved one root, check if there are any other + getRoots(successCallback); + }, function(e) { + console.error(e); + // in case of an error, return the roots we have so far + successCallback(roots); + }); + } else { + if (!name_to_root) { + name_to_root = {}; + for (var i = 0; i < roots.length; ++i) { + name_to_root[roots[i].filesystemName] = roots[i]; + } + } + successCallback(roots.slice()); + } + } + + function strncmp(str1, str2, n) { + str1 = str1.substring(0, n); + str2 = str2.substring(0, n); + return ((str1 === str2) ? 0 : ((str1 > str2) ? 1 : -1 )); + } + + function findFilesystem(uri) { + var nativeUrl = getNativeUrl(uri); + for (var i = roots.length - 1; i > 0; --i) { + if (0 === strncmp(nativeUrl, roots[i].nativeURL, roots[i].nativeURL.length)) { + return roots[i]; + } + } + + return roots[0]; // root filesystem + } + + function isRootUri(uri) { + var fs = findFilesystem(uri); + return (fs.nativeURL === getNativeUrl(uri)); + } + + // http://www.w3.org/TR/2011/WD-file-system-api-20110419/#naming-restrictions + var disallowedCharacters = [ '/', '\\', '<', '>', ':', '?', '*', '"', '|' ]; + + function isValidFileName(name) { + for (var i = 0; i < disallowedCharacters.length; ++i) { + if (-1 !== name.indexOf(disallowedCharacters[i])) { + return false; + } + } + + return true; + } + + var localhost = '//localhost/' + var cdvPrefix = 'cdvfile:///'; + + function internalUrlToNativePath(url) { + var input = url; + + // skip parameters + url = url.split('?')[0]; + + // remove localhost + url = url.replace(localhost, '///'); + + if (0 === url.indexOf(cdvPrefix)) { + // cdvfile protocol + url = url.substring(cdvPrefix.length); + + var idx = url.indexOf('/'); + + if (-1 !== idx) { + var fsName = url.substring(0, idx); + var fullPath = url.substring(idx); + url = name_to_root[fsName] ? name_to_root[fsName].nativeURL + fullPath : undefined; + } else { + // malformed URL + url = undefined; + } + } else if (0 === url.indexOf(filePrefix)) { + // check if the filesystem for this URL exists + var found = false; + for (var i = 0; i < roots.length && !found; ++i) { + if (0 === url.indexOf(roots[i].nativeURL)) { + found = true; + } + } + + if (!found) { + url = undefined; + } + } else { + // backwards compatibility, device absolute path + // only TEMPORARY and PERSISTENT paths are allowed + url = filePrefix + url.substring(1); // skip '/' + if (0 !== url.indexOf(name_to_root.temporary.nativeURL) && + 0 !== url.indexOf(name_to_root.persistent.nativeURL)) { + url = undefined; + } + } + + if (url) { + url = decodeURI(getNativeUrl(url)); + } else { + console.error('Failed to decode internal URL: ' + input); + } + + return url; + } + + return { + getRoots: getRoots, + findFilesystem: findFilesystem, + getName: getName, + getFullPath: getFullPath, + getNativeUrl: getNativeUrl, + stripTrailingSlash: stripTrailingSlash, + createEntry: createEntry, + isRootUri: isRootUri, + isValidFileName: isValidFileName, + internalUrlToNativePath: internalUrlToNativePath + }; +})(); + +module.exports = rootUtils; + +//TODO: remove when added to public cordova repository -> begin +}); +//TODO: remove -> end