Repository: cordova-android
Updated Branches:
  refs/heads/master d9814c554 -> ef268e232


CB-10963: Handle overlapping permission requests from plugins

This closes #285


Project: http://git-wip-us.apache.org/repos/asf/cordova-android/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-android/commit/ef268e23
Tree: http://git-wip-us.apache.org/repos/asf/cordova-android/tree/ef268e23
Diff: http://git-wip-us.apache.org/repos/asf/cordova-android/diff/ef268e23

Branch: refs/heads/master
Commit: ef268e23206f3378d5c8c5dd279d2821830766b2
Parents: d9814c5
Author: Richard Knoll <richard.b.kn...@gmail.com>
Authored: Fri Mar 25 11:07:27 2016 -0700
Committer: Richard Knoll <richard.b.kn...@gmail.com>
Committed: Tue Mar 29 15:14:41 2016 -0700

----------------------------------------------------------------------
 .../src/org/apache/cordova/CallbackMap.java     | 65 ++++++++++++++++++++
 .../apache/cordova/CordovaInterfaceImpl.java    | 21 +++----
 2 files changed, 75 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/ef268e23/framework/src/org/apache/cordova/CallbackMap.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/CallbackMap.java 
b/framework/src/org/apache/cordova/CallbackMap.java
new file mode 100644
index 0000000..050daa0
--- /dev/null
+++ b/framework/src/org/apache/cordova/CallbackMap.java
@@ -0,0 +1,65 @@
+/*
+       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;
+
+import android.util.Pair;
+import android.util.SparseArray;
+
+/**
+ * Provides a collection that maps unique request codes to CordovaPlugins and 
Integers.
+ * Used to ensure that when plugins make requests for runtime permissions, 
those requests do not
+ * collide with requests from other plugins that use the same request code 
value.
+ */
+public class CallbackMap {
+    private int currentCallbackId = 0;
+    private SparseArray<Pair<CordovaPlugin, Integer>> callbacks;
+
+    public CallbackMap() {
+        this.callbacks = new SparseArray<Pair<CordovaPlugin, Integer>>();
+    }
+
+    /**
+     * Stores a CordovaPlugin and request code and returns a new unique 
request code to use
+     * in a permission request.
+     *
+     * @param receiver      The plugin that is making the request
+     * @param requestCode   The original request code used by the plugin
+     * @return              A unique request code that can be used to retrieve 
this callback
+     *                      with getAndRemoveCallback()
+     */
+    public synchronized int registerCallback(CordovaPlugin receiver, int 
requestCode) {
+        int mappedId = this.currentCallbackId++;
+        callbacks.put(mappedId, new Pair<CordovaPlugin, Integer>(receiver, 
requestCode));
+        return mappedId;
+    }
+
+    /**
+     * Retrieves and removes a callback stored in the map using the mapped 
request code
+     * obtained from registerCallback()
+     *
+     * @param mappedId      The request code obtained from registerCallback()
+     * @return              The CordovaPlugin and orignal request code that 
correspond to the
+     *                      given mappedCode
+     */
+    public synchronized Pair<CordovaPlugin, Integer> getAndRemoveCallback(int 
mappedId) {
+        Pair<CordovaPlugin, Integer> callback = callbacks.get(mappedId);
+        callbacks.remove(mappedId);
+        return callback;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/ef268e23/framework/src/org/apache/cordova/CordovaInterfaceImpl.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/CordovaInterfaceImpl.java 
b/framework/src/org/apache/cordova/CordovaInterfaceImpl.java
index d1420b6..db94e66 100644
--- a/framework/src/org/apache/cordova/CordovaInterfaceImpl.java
+++ b/framework/src/org/apache/cordova/CordovaInterfaceImpl.java
@@ -25,6 +25,7 @@ import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.Bundle;
 import android.util.Log;
+import android.util.Pair;
 
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -42,8 +43,8 @@ public class CordovaInterfaceImpl implements CordovaInterface 
{
     protected PluginManager pluginManager;
 
     protected ActivityResultHolder savedResult;
+    protected CallbackMap permissionResultCallbacks;
     protected CordovaPlugin activityResultCallback;
-    protected CordovaPlugin permissionResultCallback;
     protected String initCallbackService;
     protected int activityResultRequestCode;
     protected boolean activityWasDestroyed = false;
@@ -56,6 +57,7 @@ public class CordovaInterfaceImpl implements CordovaInterface 
{
     public CordovaInterfaceImpl(Activity activity, ExecutorService threadPool) 
{
         this.activity = activity;
         this.threadPool = threadPool;
+        this.permissionResultCallbacks = new CallbackMap();
     }
 
     @Override
@@ -208,24 +210,21 @@ public class CordovaInterfaceImpl implements 
CordovaInterface {
      */
     public void onRequestPermissionResult(int requestCode, String[] 
permissions,
                                           int[] grantResults) throws 
JSONException {
-        if(permissionResultCallback != null)
-        {
-            permissionResultCallback.onRequestPermissionResult(requestCode, 
permissions, grantResults);
-            permissionResultCallback = null;
+        Pair<CordovaPlugin, Integer> callback = 
permissionResultCallbacks.getAndRemoveCallback(requestCode);
+        if(callback != null) {
+            callback.first.onRequestPermissionResult(callback.second, 
permissions, grantResults);
         }
     }
 
     public void requestPermission(CordovaPlugin plugin, int requestCode, 
String permission) {
-        permissionResultCallback = plugin;
         String[] permissions = new String [1];
         permissions[0] = permission;
-        getActivity().requestPermissions(permissions, requestCode);
+        requestPermissions(plugin, requestCode, permissions);
     }
 
-    public void requestPermissions(CordovaPlugin plugin, int requestCode, 
String [] permissions)
-    {
-        permissionResultCallback = plugin;
-        getActivity().requestPermissions(permissions, requestCode);
+    public void requestPermissions(CordovaPlugin plugin, int requestCode, 
String [] permissions) {
+        int mappedRequestCode = 
permissionResultCallbacks.registerCallback(plugin, requestCode);
+        getActivity().requestPermissions(permissions, mappedRequestCode);
     }
 
     public boolean hasPermission(String permission)


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

Reply via email to