Committed! Would be great to get more platforms on board. These are super
useful!


On Tue, May 13, 2014 at 9:53 PM, Andrew Grieve <agri...@chromium.org> wrote:

> 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 <agri...@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 <purplecabb...@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 <agri...@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 <purplecabb...@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 <
>> purplecabb...@gmail.com
>> > > >wrote:
>> > >
>> > > > Yeah almost. Still brewing a little.
>> > > > Give me a couple hours.
>> > > >
>> > > >
>> > > >
>> > > > > On May 12, 2014, at 10:05 AM, Andrew Grieve <agri...@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 <
>> agri...@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 <
>> > agri...@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?
>> > > > >>
>> > > >
>> > >
>> >
>>
>
>

Reply via email to