Return-Path: X-Original-To: apmail-cordova-commits-archive@www.apache.org Delivered-To: apmail-cordova-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id BDBED119A9 for ; Thu, 20 Feb 2014 16:07:54 +0000 (UTC) Received: (qmail 21192 invoked by uid 500); 20 Feb 2014 16:07:54 -0000 Delivered-To: apmail-cordova-commits-archive@cordova.apache.org Received: (qmail 21155 invoked by uid 500); 20 Feb 2014 16:07:52 -0000 Mailing-List: contact commits-help@cordova.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cordova.apache.org Delivered-To: mailing list commits@cordova.apache.org Received: (qmail 21098 invoked by uid 99); 20 Feb 2014 16:07:51 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 20 Feb 2014 16:07:51 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 325E892981C; Thu, 20 Feb 2014 16:07:51 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ian@apache.org To: commits@cordova.apache.org Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: git commit: Rewrite file-extras plugin as file-system-roots Date: Thu, 20 Feb 2014 16:07:51 +0000 (UTC) Repository: cordova-plugins Updated Branches: refs/heads/master b24a99e3b -> 31597ca5a Rewrite file-extras plugin as file-system-roots This plugin has been updated to work with the new version of File. It now comes with additional documentation describing the available filesystem roots, how to use them in applications, and how to configure them. The old file-extras plugin still remains, but should be considered deprecated. Project: http://git-wip-us.apache.org/repos/asf/cordova-plugins/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugins/commit/31597ca5 Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugins/tree/31597ca5 Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugins/diff/31597ca5 Branch: refs/heads/master Commit: 31597ca5a7ae5606597d4fe7f589a7fb8c566dc8 Parents: b24a99e Author: Ian Clelland Authored: Wed Feb 12 10:35:00 2014 -0500 Committer: Ian Clelland Committed: Thu Feb 20 11:07:21 2014 -0500 ---------------------------------------------------------------------- file-system-roots/README.md | 65 +++++++++ file-system-roots/android/FileSystemRoots.java | 148 +++++++++++++++++++ file-system-roots/filesystemroots.js | 89 ++++++++++++ file-system-roots/ios/FileSystemRoots.m | 152 ++++++++++++++++++++ file-system-roots/plugin.xml | 55 +++++++ 5 files changed, 509 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/31597ca5/file-system-roots/README.md ---------------------------------------------------------------------- diff --git a/file-system-roots/README.md b/file-system-roots/README.md new file mode 100644 index 0000000..68ed7f9 --- /dev/null +++ b/file-system-roots/README.md @@ -0,0 +1,65 @@ +org.apache.cordova.file-system-roots plugin +=========================================== + +This plugin grants a Cordova application access to several additional filesystem roots, and provides a cross-platform means of accessing these filesystems based on their intended purpose. + +The set of available filesystems depends on the platform. + +Android +------- + + - files: The application's internal file storage directory + - files-external: The application's external file storage directory + - sdcard: The global external file storage directory (this is the root of the SD card, if one is installed) + - cache: The application's internal cache directory + - cache-external: The application's external cache directory + - root: The entire device filesystem + +Android also supports a special filesystem named "documents", which represents a "/Documents/" subdirectory within the "files" filesystem. + +iOS +--- + + - library: The application's Library directory + - documents: The application's Documents directory + - cache: The application's Cache directory + - app-bundle: The application's bundle; the location of the app itself on disk + - root: The entire device filesystem + +By default, the library and documents directories can be synced to iCloud. You can also request two additional filesystems, "library-nosync" and "documents-nosync", which represent a special non-synced directory within the Library or Documents filesystem. + +Configuring the plugin +---------------------- + +The set of available filesystems can be configured at build time per-platform. Both iOS and Android recognize a tag in `config.xml` which names the filesystems to be installed. The defaults for these preferences, if not set, are + + + + + +These defaults contain all available filesystems except for "root". + +Accessing the filesystems +------------------------- + +The simplest method of using these new filesystems is to call `cordova.filesystem.getFilesystem` with the name of the filesystem you want to use. + + cordova.filesystem.getFilesystemRoot(filesystemName, successCallback, errorCallback); + +If successful, `successCallback` will be called with a `DirectoryEntry` object representing the root of the filesystem. Otherwise, `errorCallback` will be called with a `FileError`. + +It is also possible to request a `DirectoryEntry` object for a particular purpose. This provides a cross-platform way of accessing the various filesystem locations. + + cordova.filesystem.getDirectoryForPurpose(purpose, options, successCallback, failureCallback) + +will call successCallback with a `DirectoryEntry` object suitable for the specified purpose. + +The following string constants are defined for the `purpose` field: + + data + documents + cache + temp (returns the TEMPORARY filesystem) + app-bundle (iOS only) + +The `options` field is an object. On iOS, it is possible to set it to `{syncable: false}` to obtain the non-synced versions of `data` or `documents`. On Android, you can set `{sandboxed: false}` to get the external (not confined to your app) versions of `data`, `documents` or `cache`. http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/31597ca5/file-system-roots/android/FileSystemRoots.java ---------------------------------------------------------------------- diff --git a/file-system-roots/android/FileSystemRoots.java b/file-system-roots/android/FileSystemRoots.java new file mode 100644 index 0000000..a75c14a --- /dev/null +++ b/file-system-roots/android/FileSystemRoots.java @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * +*/ +package org.apache.cordova.filesystemroots; + +import android.app.Activity; +import android.content.Context; +import android.os.Environment; +import android.util.Log; + +import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaArgs; +import org.apache.cordova.CordovaInterface; +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.CordovaWebView; +import org.apache.cordova.file.FileUtils; +import org.apache.cordova.file.LocalFilesystem; +import org.json.JSONException; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; + +public class FileSystemRoots extends CordovaPlugin { + private static final int PURPOSE_DATA = 0; + private static final int PURPOSE_DOCUMENTS = 1; + private static final int PURPOSE_CACHE = 2; + private static final int PURPOSE_TEMP = 3; + private static final String TAG = "file-system-roots"; + + private HashSet installedFilesystems; + private HashMap availableFilesystems; + + @Override + public void initialize(CordovaInterface cordova, CordovaWebView webView) { + super.initialize(cordova, webView); + + Activity activity = cordova.getActivity(); + Context context = activity.getApplicationContext(); + + availableFilesystems = new HashMap(); + availableFilesystems.put("files", context.getFilesDir().getAbsolutePath()); + availableFilesystems.put("files-external", context.getExternalFilesDir(null).getAbsolutePath()); + availableFilesystems.put("documents", new File(context.getFilesDir(), "Documents").getAbsolutePath()); + availableFilesystems.put("sdcard", Environment.getExternalStorageDirectory().getAbsolutePath()); + availableFilesystems.put("cache", context.getCacheDir().getAbsolutePath()); + availableFilesystems.put("cache-external", context.getExternalCacheDir().getAbsolutePath()); + availableFilesystems.put("root", "/"); + + installedFilesystems = new HashSet(); + + String filesystemsStr = activity.getIntent().getStringExtra("androidextrafilesystems"); + if (filesystemsStr == null) { + filesystemsStr = "files,files-external,documents,sdcard,cache,cache-external"; + } + + String[] filesystems = filesystemsStr.split(","); + + FileUtils filePlugin = (FileUtils)webView.pluginManager.getPlugin("File"); + if (filePlugin != null) { + /* Register filesystems in order */ + for (String fsName : filesystems) { + if (!installedFilesystems.contains(fsName)) { + String fsRoot = availableFilesystems.get(fsName); + if (fsRoot != null) { + File newRoot = new File(fsRoot); + if (newRoot.mkdirs() || newRoot.isDirectory()) { + filePlugin.registerFilesystem(new LocalFilesystem(fsName, cordova, fsRoot)); + installedFilesystems.add(fsName); + } else { + Log.d(TAG, "Unable to create root dir for fileystem \"" + fsName + "\", skipping"); + } + } else { + Log.d(TAG, "Unrecognized extra filesystem identifier: " + fsName); + } + } + } + } else { + Log.w(TAG, "File plugin not found; cannot initialize file-system-roots plugin"); + } + + } + + @Override + public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) throws JSONException { + if ("getDirectoryForPurpose".equals(action)) { + getDirectoryForPurpose(args, callbackContext); + return true; + } + + return false; + } + + private void getDirectoryForPurpose(final CordovaArgs args, final CallbackContext callbackContext) throws JSONException { + int purpose = args.getInt(0); + boolean sandboxed = args.getBoolean(1); + + String path = null; + switch (purpose) { + case PURPOSE_DATA: + if (sandboxed && installedFilesystems.contains("files")) { + path = "cdvfile://localhost/files/"; + } else if (installedFilesystems.contains("files-external")) { + path = "cdvfile://localhost/files-external/"; + } + break; + case PURPOSE_DOCUMENTS: + if (sandboxed && installedFilesystems.contains("documents")) { + path = "cdvfile://localhost/documents/"; + } else if (installedFilesystems.contains("scdard")) { + path = "cdvfile://localhost/sdcard/"; + } + break; + case PURPOSE_TEMP: + path = "cdvfile://localhost/temporary/"; + case PURPOSE_CACHE: + if (sandboxed && installedFilesystems.contains("cache")) { + path = "cdvfile://localhost/cache/"; + } else if (installedFilesystems.contains("cache-external")) { + path = "cdvfile://localhost/cache-external"; + } + break; + } + + if (path == null) { + callbackContext.error("No path found."); + return; + } + + callbackContext.success(path); + } +} http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/31597ca5/file-system-roots/filesystemroots.js ---------------------------------------------------------------------- diff --git a/file-system-roots/filesystemroots.js b/file-system-roots/filesystemroots.js new file mode 100644 index 0000000..fa51afb --- /dev/null +++ b/file-system-roots/filesystemroots.js @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 exec = require('cordova/exec'); +var argscheck = require('cordova/argscheck'); + + +// Open Discussion: +// * Should we have a purpose to expose the assets? +// * Would it be any different from resolveLocalFileSystemURL('/') +// * Should we instead expose URLs instead of DirectoryEntry objects? +// * e.g. On iOS, app-data://icloud=yes/, app-documents://icloud=no/, app-temp://, app-bundle:// +// * e.g. On Android, could use same schemes for 3.0+, or use content://cordova-app/app-data://... for 2.3 +// * This would mean APIs could be synchronous, and platform-specific locations can be kept on native side. +// * This would allow things to be used as URLs for images. +// * APIs (such as FileTransfer) work better with URLs (Paths are annoying, esp with Windows using \) +// * Entry have a toURL() already. Without custom schemes, it won't work for Android resources & assets +// * Add support resolveLocalFileSystemURL()? + + +var Purpose = { + 'data': 0, // General application data (default) + 'documents': 1, // Files that are meaningful to other applciations (e.g. Office files) + 'cache': 2, // Temporary files that should survive app restarts + 'temp': 3, // Files that can should be deleted on app restarts + 'app-bundle': 4 // The application bundle (iOS only) +}; + +/** + * Supplies a DirectoryEntry that matches the given constraints to the given callback. + */ +exports.getDirectoryForPurpose = function(purpose, options, successCallback, failureCallback) { + argscheck.checkArgs('sOfF', 'cordova.filesystem.getDirectoryForPurpose', arguments); + var augmentedSuccessCallback = successCallback && function(fullPath) { + resolveLocalFileSystemURL(fullPath, successCallback, failureCallback); + }; + + var purposeInt = Purpose[purpose]; + if (typeof purposeInt == 'undefined') { + throw new Error('getDirectoryForPurpose: invalid purpose: ' + purpose); + } + options = options || {}; + + var sandboxed = typeof options.sandboxed == 'undefined' ? true : !!options.sandboxed; + var syncable = typeof options.syncable == 'undefined' ? true : !!options.syncable; + + var args = [purposeInt, sandboxed, syncable]; + exec(augmentedSuccessCallback, failureCallback, "FileSystemRoots", "getDirectoryForPurpose", args); +}; + +exports.getDataDirectory = function(syncable, successCallback) { + argscheck.checkArgs('*f', 'cordova.filesystem.getDataDirectory', arguments); + exports.getDirectoryForPurpose('data', { syncable: syncable }, successCallback); +}; + +// On Android, this is the root of the SD card. +exports.getDocumentsDirectory = function(successCallback) { + exports.getDirectoryForPurpose('documents', { syncable: true, sandboxed: false }, successCallback); +}; + +exports.getTempDirectory = function(successCallback) { + exports.getDirectoryForPurpose('temp', null, successCallback); +}; + +exports.getCacheDirectory = function(successCallback) { + exports.getDirectoryForPurpose('cache', null, successCallback); +}; + +exports.getFileSystemRoot = function(fileSystemName, successCallback, failureCallback) { + argscheck.checkArgs('sfF', 'cordova.filesystem.getFileSystemRoot', arguments); + resolveLocalFileSystemURL('cdvfile://localhost/'+fileSystemName+'/', successCallback, failureCallback); +}; http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/31597ca5/file-system-roots/ios/FileSystemRoots.m ---------------------------------------------------------------------- diff --git a/file-system-roots/ios/FileSystemRoots.m b/file-system-roots/ios/FileSystemRoots.m new file mode 100644 index 0000000..b9b4f22 --- /dev/null +++ b/file-system-roots/ios/FileSystemRoots.m @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * +*/ + +#import +#import "CDVFile.h" +#import "CDVLocalFilesystem.h" + +enum FileSystemPurpose { + DATA = 0, + DOCUMENTS = 1, + CACHE = 2, + TEMP = 3, + IOS_BUNDLE = 4, +}; +typedef int FileSystemPurpose; + +@interface FileSystemRoots : CDVPlugin { + NSDictionary *availableFilesystems; + NSMutableSet *installedFilesystems; +} +@end + +@implementation FileSystemRoots + +- (void)pluginInitialize +{ + NSString *libPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]; + NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; + availableFilesystems = @{ + @"library": libPath, + @"library-nosync": [libPath stringByAppendingPathComponent:@"NoCloud"], + @"documents": docPath, + @"documents-nosync": [docPath stringByAppendingPathComponent:@"NoCloud"], + @"cache": [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0], + @"bundle": [[NSBundle mainBundle] bundlePath], + @"root": @"/" + }; + installedFilesystems = [[NSMutableSet alloc] initWithCapacity:7]; + + /* Get filesystems to be installed from settings */ + id vc = self.viewController; + + NSDictionary *settings = [vc settings]; + NSString *filesystemsStr = [settings[@"iosextrafilesystems"] lowercaseString]; + if (!filesystemsStr) { + filesystemsStr = @"library,library-nosync,documents,documents-nosync,cache,bundle"; + } + NSArray *filesystems = [filesystemsStr componentsSeparatedByString:@","]; + + /* Build non-syncable directories as necessary */ + for (NSString *nonSyncFS in @[@"library-nosync", @"documents-nosync"]) { + if ([filesystems containsObject:nonSyncFS]) { + [self makeNonSyncable:availableFilesystems[nonSyncFS]]; + } + } + + CDVFile *filePlugin = [[vc commandDelegate] getCommandInstance:@"File"]; + if (filePlugin) { + /* Register filesystems in order */ + for (NSString *fsName in filesystems) { + if (![installedFilesystems containsObject:fsName]) { + NSString *fsRoot = availableFilesystems[fsName]; + if (fsRoot) { + [filePlugin registerFilesystem:[[CDVLocalFilesystem alloc] initWithName:fsName root:fsRoot]]; + [installedFilesystems addObject:fsName]; + } else { + NSLog(@"Unrecognized extra filesystem identifier: %@", fsName); + } + } + } + } else { + NSLog(@"File plugin not found; cannot initialize file-system-roots plugin"); + } +} + +- (void)makeNonSyncable:(NSString*)path { + [[NSFileManager defaultManager] createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:nil + error:nil]; + NSURL* url = [NSURL fileURLWithPath:path]; + [url setResourceValue: [NSNumber numberWithBool: YES] + forKey: NSURLIsExcludedFromBackupKey error:nil]; + +} + +- (void)getDirectoryForPurpose:(CDVInvokedUrlCommand *)command { + FileSystemPurpose purpose = [[command argumentAtIndex:0] intValue]; + // BOOL sandboxed = [[command argumentAtIndex:1] boolValue]; + BOOL syncable = [[command argumentAtIndex:2] boolValue]; + + NSString *path = nil; + + switch (purpose) { + case DATA: + if (syncable && [installedFilesystems containsObject:@"library"]) { + path = @"cdvfile://localhost/library/"; + } else if ([installedFilesystems containsObject:@"library-nosync"]) { + path = @"cdvfile://localhost/library-nosync/"; + } + break; + case DOCUMENTS: + if (syncable && [installedFilesystems containsObject:@"documents"]) { + path = @"cdvfile://localhost/documents/"; + } else if ([installedFilesystems containsObject:@"documents-nosync"]) { + path = @"cdvfile://localhost/documents-nosync/"; + } + break; + case CACHE: + if ([installedFilesystems containsObject:@"cache"]) { + path = @"cdvfile://localhost/cache/"; + } + break; + case TEMP: + path = @"cdvfile://localhost/temporary/"; + break; + case IOS_BUNDLE: + if ([installedFilesystems containsObject:@"bundle"]) { + path = @"cdvfile://localhost/bundle/"; + } + break; + } + + CDVPluginResult *pluginResult = nil; + + if (!path) { + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR]; + } else { + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:path]; + } + + [[self commandDelegate] sendPluginResult:pluginResult callbackId:[command callbackId]]; +} + +@end http://git-wip-us.apache.org/repos/asf/cordova-plugins/blob/31597ca5/file-system-roots/plugin.xml ---------------------------------------------------------------------- diff --git a/file-system-roots/plugin.xml b/file-system-roots/plugin.xml new file mode 100644 index 0000000..9058892 --- /dev/null +++ b/file-system-roots/plugin.xml @@ -0,0 +1,55 @@ + + + + + + + + File Extras + + + + + + + + + + + + + + + + + + + + + + + + + + + +