cordova-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andrew Grieve <agri...@chromium.org>
Subject Re: CB-285 (FileSystem paths)
Date Wed, 14 May 2014 01:53:54 GMT
I don't think we should try to make cross-platform-compromise decisions on
this one (e.g. mapping desktop to /mnt/sdcard). requestLocalFileSystem()
gives a x-platform "data" and "temp" directory. What I want to expose here
are the platform-specific directories (requires users to know their
platform).

This puts properties on "cordova.file.fooDirectory".
Paths that don't exist on a platform are set to null.



Proposed patch (missing docs, but I'll add before committing):

>From 1a5d8e3306e9b31aa5a4dec136451b92264ee01a Mon Sep 17 00:00:00 2001
From: Andrew Grieve <agrieve@chromium.org>
Date: Tue, 13 May 2014 21:46:13 -0400
Subject: [PATCH] CB-285 Add cordova.file.*Directory properties for iOS &
 Android

---
 plugin.xml                 |  9 +++++++
 src/android/FileUtils.java | 20 +++++++++++++++
 src/ios/CDVFile.m          | 30 +++++++++++++++++++++++
 www/fileSystemPaths.js     | 61
++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 120 insertions(+)
 create mode 100644 www/fileSystemPaths.js

diff --git a/plugin.xml b/plugin.xml
index 3bced58..2154ed7 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -135,6 +135,10 @@ xmlns:android="
http://schemas.android.com/apk/res/android"
         <js-module src="www/fileSystems-roots.js" name="fileSystems-roots">
             <runs/>
         </js-module>
+        <js-module src="www/fileSystemPaths.js" name="fileSystemPaths">
+            <merges target="cordova" />
+            <runs/>
+        </js-module>
     </platform>

     <!-- amazon-fireos -->
@@ -208,6 +212,11 @@ xmlns:android="
http://schemas.android.com/apk/res/android"
             <runs/>
         </js-module>

+        <js-module src="www/fileSystemPaths.js" name="fileSystemPaths">
+            <merges target="cordova" />
+            <runs/>
+        </js-module>
+
         <framework src="AssetsLibrary.framework" />
         <framework src="MobileCoreServices.framework" />
     </platform>
diff --git a/src/android/FileUtils.java b/src/android/FileUtils.java
index 5fbe1f6..9233a62 100644
--- a/src/android/FileUtils.java
+++ b/src/android/FileUtils.java
@@ -344,6 +344,8 @@ public class FileUtils extends CordovaPlugin {
                     callbackContext.success(requestAllFileSystems());
                 }
             }, callbackContext);
+        } else if (action.equals("requestAllPaths")) {
+            callbackContext.success(requestAllPaths());
         } else if (action.equals("requestFileSystem")) {
             final int fstype=args.getInt(0);
             final long size = args.optLong(1);
@@ -850,6 +852,24 @@ public class FileUtils extends CordovaPlugin {
         return ret;
     }

+    private static String toDirUrl(File f) {
+        return Uri.fromFile(f).toString() + '/';
+    }
+
+    private JSONObject requestAllPaths() throws JSONException {
+        Context context = cordova.getActivity();
+        JSONObject ret = new JSONObject();
+        ret.put("applicationDirectory", "file:///android_asset/");
+        ret.put("applicationStorageDirectory",
toDirUrl(context.getFilesDir().getParentFile()));
+        ret.put("dataDirectory", toDirUrl(context.getFilesDir()));
+        ret.put("cacheDirectory", toDirUrl(context.getCacheDir()));
+        ret.put("externalApplicationStorageDirectory",
toDirUrl(context.getExternalFilesDir(null).getParentFile()));
+        ret.put("externalDataDirectory",
toDirUrl(context.getExternalFilesDir(null)));
+        ret.put("externalCacheDirectory",
toDirUrl(context.getExternalCacheDir()));
+        ret.put("externalRootDirectory",
toDirUrl(Environment.getExternalStorageDirectory()));
+        return ret;
+    }
+
    /**
      * Returns a JSON object representing the given File. Internal APIs
should be modified
      * to use URLs instead of raw FS paths wherever possible, when
interfacing with this plugin.
diff --git a/src/ios/CDVFile.m b/src/ios/CDVFile.m
index 11b8dd3..b22b7cf 100644
--- a/src/ios/CDVFile.m
+++ b/src/ios/CDVFile.m
@@ -458,6 +458,36 @@ NSString* const kCDVFilesystemURLPrefix = @"cdvfile";
     [self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
 }

+- (void)requestAllPaths:(CDVInvokedUrlCommand*)command
+{
+    NSString* libPath =
NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask,
YES)[0];
+    NSString* libPathSync = [libPath stringByAppendingPathComponent:@
"Cloud"];
+    NSString* libPathNoSync = [libPath stringByAppendingPathComponent:@
"NoCloud"];
+    NSString* docPath =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,
YES)[0];
+    NSString* storagePath = [libPath stringByDeletingLastPathComponent];
+    NSString* cachePath =
NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask,
YES)[0];
+
+    // Create the directories if necessary.
+    [[NSFileManager defaultManager] createDirectoryAtPath:libPathSync
withIntermediateDirectories:YES attributes:nil error:nil];
+    [[NSFileManager defaultManager] createDirectoryAtPath:libPathNoSync
withIntermediateDirectories:YES attributes:nil error:nil];
+    // Mark NoSync as non-iCloud.
+    [[NSURL fileURLWithPath:libPathNoSync] setResourceValue: [NSNumber
numberWithBool: YES]
+                                                     forKey:
NSURLIsExcludedFromBackupKey error:nil];
+
+    NSDictionary* ret = @{
+        @"applicationDirectory": [[NSURL fileURLWithPath:[[NSBundle
mainBundle] bundlePath]] absoluteString],
+        @"applicationStorageDirectory": [[NSURL
fileURLWithPath:storagePath] absoluteString],
+        @"dataDirectory": [[NSURL fileURLWithPath:libPathNoSync]
absoluteString],
+        @"syncedDataDirectory": [[NSURL fileURLWithPath:libPathSync]
absoluteString],
+        @"documentsDirectory": [[NSURL fileURLWithPath:docPath]
absoluteString],
+        @"cacheDirectory": [[NSURL fileURLWithPath:cachePath]
absoluteString],
+        @"tempDirectory": [[NSURL fileURLWithPath:NSTemporaryDirectory()]
absoluteString]
+    };
+
+    CDVPluginResult* result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_OK messageAsDictionary:ret];
+    [self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
+}
+
 /* Creates and returns a dictionary representing an Entry Object
  *
  * IN:
diff --git a/www/fileSystemPaths.js b/www/fileSystemPaths.js
new file mode 100644
index 0000000..8ef0bb8
--- /dev/null
+++ b/www/fileSystemPaths.js
@@ -0,0 +1,61 @@
+/*
+ *
+ * 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 channel = require('cordova/channel');
+
+exports.file = {
+    // Read-only directory where the application is installed.
+    applicationDirectory: null,
+    // Root of app's private writable storage
+    applicationStorageDirectory: null,
+    // Where to put app-specific data files.
+    dataDirectory: null,
+    // Cached files that should survive app restarts.
+    // Apps should not rely on the OS to delete files in here.
+    cacheDirectory: null,
+    // Android: the application space on external storage.
+    externalApplicationStorageDirectory: null,
+    // Android: Where to put app-specific data files on external storage.
+    externalDataDirectory: null,
+    // Android: the application cache on external storage.
+    externalCacheDirectory: null,
+    // Android: the external storage (SD card) root.
+    externalRootDirectory: null,
+    // iOS: Temp directory that the OS can clear at will.
+    tempDirectory: null,
+    // iOS: Holds app-specific files that should be synced (e.g. to
iCloud).
+    syncedDataDirectory: null,
+    // iOS: Files private to the app, but that are meaningful to other
applciations (e.g. Office files)
+    documentsDirectory: null
+};
+
+channel.waitForInitialization('onFileSystemPathsReady');
+channel.onCordovaReady.subscribe(function() {
+    function after(paths) {
+        for (var k in paths) {
+            exports.file[k] = paths[k];
+        }
+        channel.initializationComplete('onFileSystemPathsReady');
+    }
+    exec(after, null, 'File', 'requestAllPaths', []);
+});
+
-- 
1.8.3.4 (Apple Git-47)



On Tue, May 13, 2014 at 6:32 PM, Jesse <purplecabbage@gmail.com> wrote:

> I think it is acceptable to have the desktopDirectory, and userDirectory
> point to the same dir as documentsDirectory on devices that do not support
> un-sandboxed file locations.
>
> On Android, this would mean desktop, user, documents all equal :
>  /mnt/sdcard
>
> And on iOS :
> /var/mobile/Applications/uid/Documents
>
> Having these there is more just for when we incorporate more desktop
> environments, ie Win32 and/or Mac.
> I am fine with removing them, however, we have to be mindful that there are
> potentially many more file locations. For example, WinRT ( Windows8.1 +
> WP8.1 ) support the downloads folder, as well as 'known' folders [1] [2]
>
>
> [1]
>
> http://msdn.microsoft.com/en-ca/library/windows/apps/windows.storage.knownfolders.aspx
> [2]
>
> http://msdn.microsoft.com/en-ca/library/windows/apps/windows.storage.downloadsfolder.aspx
>
>
>
> @purplecabbage
> risingj.com
>
>
> On Tue, May 13, 2014 at 1:57 PM, Andrew Grieve <agrieve@chromium.org>
> wrote:
>
> > Thanks Jesse,
> >
> > Less async is definitely nicer.
> >
> > Providing URLs vs DirectoryEntry I don't think is a huge difference
> either,
> > so fine with that (although it means you need to do an async call on the
> > URL to get a DirectoryEntry in order to create a file). Often though, you
> > just use the URLs with Camera FileTransfer, so there are some cases where
> > it's nice.
> >
> > Don't think desktopDirectory or userDirectory make sense since apps are
> > sandboxed these days.
> >
> > Will take a stab at a commit and report back via pull request.
> >
> >
> >
> > On Tue, May 13, 2014 at 4:37 PM, Jesse <purplecabbage@gmail.com> wrote:
> >
> > > Okay, here goes.
> > >
> > > Re:
> > >
> > >
> > > cordova.plugins.file.getDirectoryForPurpose(purpose, options, win,
> fail)
> > > Where purpose can be one of:
> > > 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)
> > > }
> > > // And the aliases
> > > cordova.plugins.file.getDataDirectory(syncable, win)
> > > cordova.plugins.file.getDocumentsDirectory(win)
> > > cordova.plugins.file.getTempDirectory(win)
> > > cordova.plugins.file.getCacheDirectory(win)
> > >
> > >
> > > Ultimately these will never change while the app running, why not just
> > have
> > > them be properties that are populated on startup?
> > > Also, given that they won't change, the async alias calls would not
> > > required.
> > >
> > > My suggestion is based in part on the Adobe Air File class which solves
> > > many of the same problems[1]
> > >
> > > I would rather see an API that looked like :
> > >
> > > // a storage directory unique to each installed application
> > > File.applicationStorageDirectory;
> > > // the read-only directory where the application is installed (along
> with
> > > any installed assets)
> > > File.applicationDirectory;
> > >  // the user's desktop directory, not available on all devices
> > > File.desktopDirectory;
> > >  // the user's documents directory, not available on all devices
> > > File.documentsDirectory;
> > > // Cached files that should survive app restarts
> > > File.cacheDirectory;
> > >
> > > // temp will only live for the lifetime of the app, so if you want a
> ref,
> > > you will have to keep it.
> > > // note also that you can create several temp directories if you want.
> > > var tempDir;
> > > File.createTempDirectory(function onSuccess(dirResult){
> > >     tempDir = dirResult;
> > > },function onError(errResult){
> > >     tempDir = null;
> > >     console.log("Error creating temp directory :" +
> > > JSON.stringify(errResult));
> > > });
> > >
> > > As an altenative, a root temp dir could be created when the app
> launches,
> > > making this async call unnecessary, and then these could be referenced
> > just
> > > like the other dirs
> > > That would make this just :
> > >
> > > // location unknown, and volatile
> > > File.tempDirectory;
> > >
> > >
> > > [1]
> > >
> > >
> >
> http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/filesystem/File.html
> > >
> > >
> > >
> > > @purplecabbage
> > > risingj.com
> > >
> > >
> > > On Tue, May 13, 2014 at 9:02 AM, purplecabbage <
> purplecabbage@gmail.com
> > > >wrote:
> > >
> > > > Yeah almost. Still brewing a little.
> > > > Give me a couple hours.
> > > >
> > > >
> > > >
> > > > > On May 12, 2014, at 10:05 AM, Andrew Grieve <agrieve@chromium.org>
> > > > wrote:
> > > > >
> > > > > Now that email works again - Jesse, were you thinking of proposing
> a
> > > > tweaks
> > > > > API, or something different altogether.
> > > > > New related bug here:
> > > > >
> > > > > https://issues.apache.org/jira/browse/CB-6670
> > > > >
> > > > >
> > > > >> On Tue, May 6, 2014 at 6:21 PM, Brian LeRoux <b@brian.io>
wrote:
> > > > >>
> > > > >> That is a very good point! I say it is good enough for now.
> > Something
> > > to
> > > > >> flag for our W3C friends to look at and consider in the spec.
> > > > >>
> > > > >>
> > > > >> On Tue, May 6, 2014 at 1:43 PM, Andrew Grieve <
> agrieve@chromium.org
> > >
> > > > >> wrote:
> > > > >>
> > > > >>> There are two types of config for file:
> > > > >>> 1. You can do is disable parts of the filesystem (doubt anyone
> > would
> > > do
> > > > >>> this)
> > > > >>> 2. You can switch where PERSISTENT filesystem maps to (sane
place
> > vs
> > > > >> legacy
> > > > >>> place)
> > > > >>>
> > > > >>> What's missing is a way to retrieve the paths that you might
> want.
> > No
> > > > >>> configuration required for this part.
> > > > >>>
> > > > >>> I'd like to avoid making the calls look like they are a part
of
> the
> > > > file
> > > > >>> spec, so that users won't be tempted to think that it would
work
> > in a
> > > > >>> non-Cordova environment.
> > > > >>>
> > > > >>>
> > > > >>>> On Tue, May 6, 2014 at 1:47 PM, Brian LeRoux <b@brian.io>
> wrote:
> > > > >>>>
> > > > >>>> This plugin is helpful though I can't help but wonder
if we
> can't
> > > > >>> shoehorn
> > > > >>>> into specs (or at least provide spec feedback).
> > > > >>>>
> > > > >>>> Right now all config is done w/ config.xml instead of
> programmatic
> > > (?)
> > > > >>>>
> > > > >>>>
> > > > >>>> On Tue, May 6, 2014 at 7:06 AM, Andrew Grieve <
> > agrieve@chromium.org
> > > >
> > > > >>>> wrote:
> > > > >>>>
> > > > >>>>> Closer than ever to resolving this (woo!)
> > > > >>>>>
> > > > >>>>> The file plugin is now able to read & write to
roots on the
> > > > >> filesystem
> > > > >>>>> beyond PERSISTENT and TEMPORARY on iOS, Android,
and BlackBerry
> > > (and
> > > > >>>> maybe
> > > > >>>>> others?)
> > > > >>>>>
> > > > >>>>> However, you still can't query for the location of
these places
> > > > >> (doh!)
> > > > >>>>>
> > > > >>>>> There's a file-extras plugin in cordova-labs:
> > > > >>
> > > >
> > >
> >
> https://git-wip-us.apache.org/repos/asf?p=cordova-labs.git;a=blob;f=file-extras/fileextras.js;h=1f8f88f7222bd4022f2f802f6825c189b10445d9;hb=aaf61d4
> > > > >>>>>
> > > > >>>>> That was used to experiment with an API for this.
I think the
> API
> > > is
> > > > >>>> pretty
> > > > >>>>> much fine, and I'd like to add it to the core file
plugin
> rather
> > > than
> > > > >>>> have
> > > > >>>>> it as a separate plugin.
> > > > >>>>>
> > > > >>>>> This would add:
> > > > >>>>> cordova.plugins.file.getDirectoryForPurpose(purpose,
options,
> > win,
> > > > >>> fail)
> > > > >>>>>
> > > > >>>>> Where purpose can be one of:
> > > > >>>>> 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)
> > > > >>>>> }
> > > > >>>>>
> > > > >>>>> And also add convenience wrappers:
> > > > >>>>> cordova.plugins.file.getDataDirectory(syncable, win)
> > > > >>>>> cordova.plugins.file.getDocumentsDirectory(win)
> > > > >>>>> cordova.plugins.file.getTempDirectory(win)
> > > > >>>>> cordova.plugins.file.getCacheDirectory(win)
> > > > >>>>>
> > > > >>>>>
> > > > >>>>> Any comments on this?
> > > > >>
> > > >
> > >
> >
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message