Skip to content

Commit 1e2593f

Browse files
author
Raghav Katyal
committed
CB-10798, CB-10384: Fixing permissions for Marshmallow. This closes apache#170
1 parent 61c0f76 commit 1e2593f

File tree

1 file changed

+90
-31
lines changed

1 file changed

+90
-31
lines changed

src/android/FileUtils.java

Lines changed: 90 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,11 @@ public class FileUtils extends CordovaPlugin {
7373
* Permission callback codes
7474
*/
7575

76-
public static final int READ_PERM = 0;
77-
public static final int WRITE_PERM = 1;
76+
public static final int GET_FILE_CALLBACK_CODE = 0;
77+
public static final int WRITE_CALLBACK_CODE = 1;
78+
public static final int GET_DIRECTORY_CALLBACK_CODE = 2;
79+
public static final int WRITE = 3;
80+
public static final int READ = 4;
7881

7982
public static int UNKNOWN_ERR = 1000;
8083

@@ -347,19 +350,17 @@ else if (action.equals("write")) {
347350
threadhelper( new FileOp( ){
348351
public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
349352
String fname=args.getString(0);
353+
String nativeURL = resolveLocalFileSystemURI(fname).getString("nativeURL");
350354
String data=args.getString(1);
351355
int offset=args.getInt(2);
352356
Boolean isBinary=args.getBoolean(3);
353-
/*
354-
* If we don't have the package name in the path, we're reading and writing to places we need permission for
355-
*/
356-
if(fname.contains(cordova.getActivity().getPackageName()) ||
357-
hasReadPermission()) {
358-
long fileSize = write(fname, data, offset, isBinary);
359-
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
357+
358+
if(needPermission(nativeURL, WRITE)) {
359+
getWritePermission();
360360
}
361361
else {
362-
getWritePermission();
362+
long fileSize = write(fname, data, offset, isBinary);
363+
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
363364
}
364365

365366
}
@@ -433,28 +434,41 @@ public void run(JSONArray args) throws JSONException, IOException {
433434
else if (action.equals("getDirectory")) {
434435
threadhelper( new FileOp( ){
435436
public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
436-
String dirname=args.getString(0);
437-
String path=args.getString(1);
438-
JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
439-
callbackContext.success(obj);
437+
String dirname = args.getString(0);
438+
String path = args.getString(1);
439+
String nativeURL = resolveLocalFileSystemURI(dirname).getString("nativeURL");
440+
boolean containsCreate = (args.isNull(2)) ? false : args.getJSONObject(2).optBoolean("create", false);
441+
442+
if(containsCreate && needPermission(nativeURL, WRITE)) {
443+
getPermissionDir(WRITE);
444+
}
445+
else if(!containsCreate && needPermission(nativeURL, READ)) {
446+
getPermissionDir(READ);
447+
}
448+
else {
449+
JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
450+
callbackContext.success(obj);
451+
}
440452
}
441453
}, rawArgs, callbackContext);
442454
}
443455
else if (action.equals("getFile")) {
444456
threadhelper( new FileOp( ){
445457
public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
446-
String dirname=args.getString(0);
447-
/*
448-
* If we don't have the package name in the path, we're reading and writing to places we need permission for
449-
*/
450-
if(dirname.contains(cordova.getActivity().getPackageName()) ||
451-
hasReadPermission()) {
452-
String path = args.getString(1);
453-
JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
454-
callbackContext.success(obj);
458+
String dirname = args.getString(0);
459+
String path = args.getString(1);
460+
String nativeURL = resolveLocalFileSystemURI(dirname).getString("nativeURL");
461+
boolean containsCreate = (args.isNull(2)) ? false : args.getJSONObject(2).optBoolean("create", false);
462+
463+
if(containsCreate && needPermission(nativeURL, WRITE)) {
464+
getPermissionFile(WRITE);
465+
}
466+
else if(!containsCreate && needPermission(nativeURL, READ)) {
467+
getPermissionFile(READ);
455468
}
456469
else {
457-
getReadPermission();
470+
JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
471+
callbackContext.success(obj);
458472
}
459473
}
460474
}, rawArgs, callbackContext);
@@ -533,14 +547,27 @@ public void run(JSONArray args) throws FileNotFoundException, JSONException, Mal
533547
return true;
534548
}
535549

536-
private void getReadPermission() {
537-
PermissionHelper.requestPermission(this, READ_PERM, Manifest.permission.READ_EXTERNAL_STORAGE);
550+
private void getPermissionFile(int permissionType) {
551+
if(permissionType == READ) {
552+
PermissionHelper.requestPermission(this, GET_FILE_CALLBACK_CODE, Manifest.permission.READ_EXTERNAL_STORAGE);
553+
}
554+
else {
555+
PermissionHelper.requestPermission(this, GET_FILE_CALLBACK_CODE, Manifest.permission.WRITE_EXTERNAL_STORAGE);
556+
}
538557
}
539558

540-
private void getWritePermission() {
541-
PermissionHelper.requestPermission(this, WRITE_PERM, Manifest.permission.WRITE_EXTERNAL_STORAGE);
559+
private void getPermissionDir(int permissionType) {
560+
if(permissionType == READ) {
561+
PermissionHelper.requestPermission(this, GET_DIRECTORY_CALLBACK_CODE, Manifest.permission.READ_EXTERNAL_STORAGE);
562+
}
563+
else {
564+
PermissionHelper.requestPermission(this, GET_DIRECTORY_CALLBACK_CODE, Manifest.permission.WRITE_EXTERNAL_STORAGE);
565+
}
542566
}
543567

568+
private void getWritePermission() {
569+
PermissionHelper.requestPermission(this, WRITE_CALLBACK_CODE, Manifest.permission.WRITE_EXTERNAL_STORAGE);
570+
}
544571

545572
private boolean hasReadPermission() {
546573
return PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
@@ -550,6 +577,26 @@ private boolean hasWritePermission() {
550577
return PermissionHelper.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
551578
}
552579

580+
private boolean needPermission(String nativeURL, int permissionType) throws JSONException {
581+
JSONObject j = requestAllPaths();
582+
String[] allowedStorageDirectories = {j.getString("applicationStorageDirectory"), j.getString("externalApplicationStorageDirectory")};
583+
584+
if(permissionType == READ && hasReadPermission()) {
585+
return false;
586+
}
587+
else if(permissionType == WRITE && hasWritePermission()) {
588+
return false;
589+
}
590+
591+
// Permission required if the native url lies outside the allowed storage directories
592+
for(String directory : allowedStorageDirectories) {
593+
if(nativeURL.startsWith(directory)) {
594+
return false;
595+
}
596+
}
597+
return true;
598+
}
599+
553600

554601
public LocalFilesystemURL resolveNativeUri(Uri nativeUri) {
555602
LocalFilesystemURL localURL = null;
@@ -1113,18 +1160,29 @@ public void onRequestPermissionResult(int requestCode, String[] permissions,
11131160
}
11141161
switch(requestCode)
11151162
{
1116-
case READ_PERM:
1163+
case GET_FILE_CALLBACK_CODE:
11171164
threadhelper( new FileOp( ){
11181165
public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
1119-
String dirname=args.getString(0);
1166+
String dirname = args.getString(0);
11201167

11211168
String path = args.getString(1);
11221169
JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
11231170
callback.success(obj);
11241171
}
11251172
}, lastRawArgs, callback);
11261173
break;
1127-
case WRITE_PERM:
1174+
case GET_DIRECTORY_CALLBACK_CODE:
1175+
threadhelper( new FileOp( ){
1176+
public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
1177+
String dirname = args.getString(0);
1178+
1179+
String path = args.getString(1);
1180+
JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
1181+
callback.success(obj);
1182+
}
1183+
}, lastRawArgs, callback);
1184+
break;
1185+
case WRITE_CALLBACK_CODE:
11281186
threadhelper( new FileOp( ){
11291187
public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
11301188
String fname=args.getString(0);
@@ -1136,6 +1194,7 @@ public void run(JSONArray args) throws JSONException, FileNotFoundException, IOE
11361194
}
11371195
}, lastRawArgs, callback);
11381196
break;
1197+
11391198
}
11401199

11411200
}

0 commit comments

Comments
 (0)