You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by rk...@apache.org on 2016/03/30 19:49:54 UTC

cordova-plugin-file git commit: CB-10977 android: Removing global state used for permission requests

Repository: cordova-plugin-file
Updated Branches:
  refs/heads/master 1e2593f42 -> 6aeb9d9d1


CB-10977 android: Removing global state used for permission requests

This closes #174


Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/commit/6aeb9d9d
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/tree/6aeb9d9d
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/diff/6aeb9d9d

Branch: refs/heads/master
Commit: 6aeb9d9d1a91c2657218e6c81dfe2b57bd46f7d7
Parents: 1e2593f
Author: Richard Knoll <ri...@gmail.com>
Authored: Mon Mar 28 12:09:21 2016 -0700
Committer: Richard Knoll <ri...@gmail.com>
Committed: Wed Mar 30 10:24:35 2016 -0700

----------------------------------------------------------------------
 plugin.xml                       |   1 +
 src/android/FileUtils.java       | 142 ++++++++++++++++------------------
 src/android/PendingRequests.java |  94 ++++++++++++++++++++++
 3 files changed, 163 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/6aeb9d9d/plugin.xml
----------------------------------------------------------------------
diff --git a/plugin.xml b/plugin.xml
index 4c79325..46dbbdb 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -146,6 +146,7 @@ to config.xml in order for the application to find previously stored files.
         <source-file src="src/android/LocalFilesystem.java" target-dir="src/org/apache/cordova/file" />
         <source-file src="src/android/ContentFilesystem.java" target-dir="src/org/apache/cordova/file" />
         <source-file src="src/android/AssetFilesystem.java" target-dir="src/org/apache/cordova/file" />
+        <source-file src="src/android/PendingRequests.java" target-dir="src/org/apache/cordova/file" />
         <source-file src="src/android/PermissionHelper.java" target-dir="src/org/apache/cordova/file" />
 
         <!-- android specific file apis -->

http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/6aeb9d9d/src/android/FileUtils.java
----------------------------------------------------------------------
diff --git a/src/android/FileUtils.java b/src/android/FileUtils.java
index e9169bc..cf193d0 100644
--- a/src/android/FileUtils.java
+++ b/src/android/FileUtils.java
@@ -73,18 +73,20 @@ public class FileUtils extends CordovaPlugin {
      * Permission callback codes
      */
 
-    public static final int GET_FILE_CALLBACK_CODE = 0;
-    public static final int WRITE_CALLBACK_CODE = 1;
-    public static final int GET_DIRECTORY_CALLBACK_CODE = 2;
+    public static final int ACTION_GET_FILE = 0;
+    public static final int ACTION_WRITE = 1;
+    public static final int ACTION_GET_DIRECTORY = 2;
+
     public static final int WRITE = 3;
     public static final int READ = 4;
 
     public static int UNKNOWN_ERR = 1000;
 
     private boolean configured = false;
-    private String lastRawArgs;
 
-    private CallbackContext callback;
+    private PendingRequests pendingRequests;
+
+
 
     /*
      * We need both read and write when accessing the storage, I think.
@@ -171,6 +173,7 @@ public class FileUtils extends CordovaPlugin {
     public void initialize(CordovaInterface cordova, CordovaWebView webView) {
     	super.initialize(cordova, webView);
     	this.filesystems = new ArrayList<Filesystem>();
+        this.pendingRequests = new PendingRequests();
 
     	String tempRoot = null;
     	String persistentRoot = null;
@@ -262,14 +265,12 @@ public class FileUtils extends CordovaPlugin {
     }
 
     public boolean execute(String action, final String rawArgs, final CallbackContext callbackContext) {
-        this.callback = callbackContext;
-        lastRawArgs = rawArgs;
         if (!configured) {
             callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, "File plugin is not configured. Please see the README.md file for details on how to update config.xml"));
             return true;
         }
         if (action.equals("testSaveLocationExists")) {
-            threadhelper( new FileOp( ){
+            threadhelper(new FileOp() {
                 public void run(JSONArray args) {
                     boolean b = DirectoryManager.testSaveLocationExists();
                     callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
@@ -356,7 +357,7 @@ public class FileUtils extends CordovaPlugin {
                     Boolean isBinary=args.getBoolean(3);
 
                     if(needPermission(nativeURL, WRITE)) {
-                        getWritePermission();
+                        getWritePermission(rawArgs, ACTION_WRITE, callbackContext);
                     }
                     else {
                         long fileSize = write(fname, data, offset, isBinary);
@@ -440,10 +441,10 @@ public class FileUtils extends CordovaPlugin {
                     boolean containsCreate = (args.isNull(2)) ? false : args.getJSONObject(2).optBoolean("create", false);
 
                     if(containsCreate && needPermission(nativeURL, WRITE)) {
-                        getPermissionDir(WRITE);
+                        getWritePermission(rawArgs, ACTION_GET_DIRECTORY, callbackContext);
                     }
                     else if(!containsCreate && needPermission(nativeURL, READ)) {
-                        getPermissionDir(READ);
+                        getReadPermission(rawArgs, ACTION_GET_DIRECTORY, callbackContext);
                     }
                     else {
                         JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
@@ -461,10 +462,10 @@ public class FileUtils extends CordovaPlugin {
                     boolean containsCreate = (args.isNull(2)) ? false : args.getJSONObject(2).optBoolean("create", false);
 
                     if(containsCreate && needPermission(nativeURL, WRITE)) {
-                        getPermissionFile(WRITE);
+                        getWritePermission(rawArgs, ACTION_GET_FILE, callbackContext);
                     }
                     else if(!containsCreate && needPermission(nativeURL, READ)) {
-                        getPermissionFile(READ);
+                        getReadPermission(rawArgs, ACTION_GET_FILE, callbackContext);
                     }
                     else {
                         JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
@@ -547,26 +548,14 @@ public class FileUtils extends CordovaPlugin {
         return true;
     }
 
-    private void getPermissionFile(int permissionType) {
-        if(permissionType == READ) {
-            PermissionHelper.requestPermission(this, GET_FILE_CALLBACK_CODE, Manifest.permission.READ_EXTERNAL_STORAGE);
-        }
-        else {
-            PermissionHelper.requestPermission(this, GET_FILE_CALLBACK_CODE, Manifest.permission.WRITE_EXTERNAL_STORAGE);
-        }
+    private void getReadPermission(String rawArgs, int action, CallbackContext callbackContext) {
+        int requestCode = pendingRequests.createRequest(rawArgs, action, callbackContext);
+        PermissionHelper.requestPermission(this, requestCode, Manifest.permission.READ_EXTERNAL_STORAGE);
     }
 
-    private void getPermissionDir(int permissionType) {
-        if(permissionType == READ) {
-            PermissionHelper.requestPermission(this, GET_DIRECTORY_CALLBACK_CODE, Manifest.permission.READ_EXTERNAL_STORAGE);
-        }
-        else {
-            PermissionHelper.requestPermission(this, GET_DIRECTORY_CALLBACK_CODE, Manifest.permission.WRITE_EXTERNAL_STORAGE);
-        }
-    }
-
-    private void getWritePermission() {
-        PermissionHelper.requestPermission(this, WRITE_CALLBACK_CODE, Manifest.permission.WRITE_EXTERNAL_STORAGE);
+    private void getWritePermission(String rawArgs, int action, CallbackContext callbackContext) {
+        int requestCode = pendingRequests.createRequest(rawArgs, action, callbackContext);
+        PermissionHelper.requestPermission(this, requestCode, Manifest.permission.WRITE_EXTERNAL_STORAGE);
     }
 
     private boolean hasReadPermission() {
@@ -1151,51 +1140,56 @@ public class FileUtils extends CordovaPlugin {
 
     public void onRequestPermissionResult(int requestCode, String[] permissions,
                                           int[] grantResults) throws JSONException {
-        for(int r:grantResults)
-        {
-            if(r == PackageManager.PERMISSION_DENIED)
+
+        final PendingRequests.Request req = pendingRequests.getAndRemove(requestCode);
+        if (req != null) {
+            for(int r:grantResults)
             {
-                callback.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, SECURITY_ERR));
+                if(r == PackageManager.PERMISSION_DENIED)
+                {
+                    req.getCallbackContext().sendPluginResult(new PluginResult(PluginResult.Status.ERROR, SECURITY_ERR));
+                    return;
+                }
             }
+            switch(req.getAction())
+            {
+                case ACTION_GET_FILE:
+                    threadhelper( new FileOp( ){
+                        public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+                            String dirname = args.getString(0);
+
+                            String path = args.getString(1);
+                            JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
+                            req.getCallbackContext().success(obj);
+                        }
+                    }, req.getRawArgs(), req.getCallbackContext());
+                    break;
+                case ACTION_GET_DIRECTORY:
+                    threadhelper( new FileOp( ){
+                        public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+                            String dirname = args.getString(0);
+
+                            String path = args.getString(1);
+                            JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
+                            req.getCallbackContext().success(obj);
+                        }
+                    }, req.getRawArgs(), req.getCallbackContext());
+                    break;
+                case ACTION_WRITE:
+                    threadhelper( new FileOp( ){
+                        public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
+                            String fname=args.getString(0);
+                            String data=args.getString(1);
+                            int offset=args.getInt(2);
+                            Boolean isBinary=args.getBoolean(3);
+                            long fileSize = write(fname, data, offset, isBinary);
+                            req.getCallbackContext().sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
+                        }
+                    }, req.getRawArgs(), req.getCallbackContext());
+                    break;
+            }
+        } else {
+           Log.d(LOG_TAG, "Received permission callback for unknown request code");
         }
-        switch(requestCode)
-        {
-            case GET_FILE_CALLBACK_CODE:
-                threadhelper( new FileOp( ){
-                    public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
-                        String dirname = args.getString(0);
-
-                        String path = args.getString(1);
-                        JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
-                        callback.success(obj);
-                    }
-                }, lastRawArgs, callback);
-                break;
-            case GET_DIRECTORY_CALLBACK_CODE:
-                threadhelper( new FileOp( ){
-                    public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
-                        String dirname = args.getString(0);
-
-                        String path = args.getString(1);
-                        JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
-                        callback.success(obj);
-                    }
-                }, lastRawArgs, callback);
-                break;    
-            case WRITE_CALLBACK_CODE:
-                threadhelper( new FileOp( ){
-                    public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
-                        String fname=args.getString(0);
-                        String data=args.getString(1);
-                        int offset=args.getInt(2);
-                        Boolean isBinary=args.getBoolean(3);
-                        long fileSize = write(fname, data, offset, isBinary);
-                        callback.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
-                    }
-                }, lastRawArgs, callback);
-                break;
-
-        }
-
     }
 }

http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/6aeb9d9d/src/android/PendingRequests.java
----------------------------------------------------------------------
diff --git a/src/android/PendingRequests.java b/src/android/PendingRequests.java
new file mode 100644
index 0000000..23d6d73
--- /dev/null
+++ b/src/android/PendingRequests.java
@@ -0,0 +1,94 @@
+/*
+       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.file;
+
+import android.util.SparseArray;
+
+import org.apache.cordova.CallbackContext;
+
+/**
+ * Holds pending runtime permission requests
+ */
+class PendingRequests {
+    private int currentReqId = 0;
+    private SparseArray<Request> requests = new SparseArray<Request>();
+
+    /**
+     * Creates a request and adds it to the array of pending requests. Each created request gets a
+     * unique result code for use with requestPermission()
+     * @param rawArgs           The raw arguments passed to the plugin
+     * @param action            The action this request corresponds to (get file, etc.)
+     * @param callbackContext   The CallbackContext for this plugin call
+     * @return                  The request code that can be used to retrieve the Request object
+     */
+    public synchronized int createRequest(String rawArgs, int action, CallbackContext callbackContext)  {
+        Request req = new Request(rawArgs, action, callbackContext);
+        requests.put(req.requestCode, req);
+        return req.requestCode;
+    }
+
+    /**
+     * Gets the request corresponding to this request code and removes it from the pending requests
+     * @param requestCode   The request code for the desired request
+     * @return              The request corresponding to the given request code or null if such a
+     *                      request is not found
+     */
+    public synchronized Request getAndRemove(int requestCode) {
+        Request result = requests.get(requestCode);
+        requests.remove(requestCode);
+        return result;
+    }
+
+    /**
+     * Holds the options and CallbackContext for a call made to the plugin.
+     */
+    public class Request {
+
+        // Unique int used to identify this request in any Android permission callback
+        private int requestCode;
+
+        // Action to be performed after permission request result
+        private int action;
+
+        // Raw arguments passed to plugin
+        private String rawArgs;
+
+        // The callback context for this plugin request
+        private CallbackContext callbackContext;
+
+        private Request(String rawArgs, int action, CallbackContext callbackContext) {
+            this.rawArgs = rawArgs;
+            this.action = action;
+            this.callbackContext = callbackContext;
+            this.requestCode = currentReqId ++;
+        }
+
+        public int getAction() {
+            return this.action;
+        }
+
+        public String getRawArgs() {
+            return rawArgs;
+        }
+
+        public CallbackContext getCallbackContext() {
+            return callbackContext;
+        }
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org