From 8981ddb681c21eb521562b860c35361291ca09be Mon Sep 17 00:00:00 2001 From: Joe Bowser Date: Tue, 14 Jul 2015 14:31:07 -0700 Subject: [PATCH] Commiting code to handle permissions, and the special case of the Geolocation Plugin --- .../org/apache/cordova/CordovaActivity.java | 81 ++++++++++--------- .../org/apache/cordova/CordovaInterface.java | 2 + .../apache/cordova/CordovaInterfaceImpl.java | 6 ++ .../src/org/apache/cordova/CordovaPlugin.java | 48 +++++++++++ .../src/org/apache/cordova/PluginManager.java | 25 ++++++ .../cordova/engine/SystemWebChromeClient.java | 9 +++ 6 files changed, 134 insertions(+), 37 deletions(-) diff --git a/framework/src/org/apache/cordova/CordovaActivity.java b/framework/src/org/apache/cordova/CordovaActivity.java index cf055c6e..171e2a83 100755 --- a/framework/src/org/apache/cordova/CordovaActivity.java +++ b/framework/src/org/apache/cordova/CordovaActivity.java @@ -109,26 +109,20 @@ public class CordovaActivity extends Activity { // need to activate preferences before super.onCreate to avoid "requestFeature() must be called before adding content" exception loadConfig(); - if(!preferences.getBoolean("ShowTitle", false)) - { + if (!preferences.getBoolean("ShowTitle", false)) { getWindow().requestFeature(Window.FEATURE_NO_TITLE); } - if(preferences.getBoolean("SetFullscreen", false)) - { + if (preferences.getBoolean("SetFullscreen", false)) { Log.d(TAG, "The SetFullscreen configuration is deprecated in favor of Fullscreen, and will be removed in a future version."); preferences.set("Fullscreen", true); } - if(preferences.getBoolean("Fullscreen", false)) - { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) - { + if (preferences.getBoolean("Fullscreen", false)) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { immersiveMode = true; - } - else - { + } else { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); + WindowManager.LayoutParams.FLAG_FULLSCREEN); } } else { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, @@ -138,12 +132,11 @@ public class CordovaActivity extends Activity { super.onCreate(savedInstanceState); cordovaInterface = makeCordovaInterface(); - if(savedInstanceState != null) - { + if (savedInstanceState != null) { cordovaInterface.restoreInstanceState(savedInstanceState); } } - + protected void init() { appView = makeWebView(); createViews(); @@ -192,7 +185,7 @@ public class CordovaActivity extends Activity { /** * Construct the default web view object. - * + *

* Override this to customize the webview that is used. */ protected CordovaWebView makeWebView() { @@ -245,13 +238,13 @@ public class CordovaActivity extends Activity { /** * Called when the activity receives a new intent - **/ + */ @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); //Forward to plugins if (this.appView != null) - this.appView.onNewIntent(intent); + this.appView.onNewIntent(intent); } /** @@ -261,7 +254,7 @@ public class CordovaActivity extends Activity { protected void onResume() { super.onResume(); LOG.d(TAG, "Resumed the activity."); - + if (this.appView == null) { return; } @@ -321,11 +314,11 @@ public class CordovaActivity extends Activity { super.onWindowFocusChanged(hasFocus); if (hasFocus && immersiveMode) { final int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_FULLSCREEN - | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; getWindow().getDecorView().setSystemUiVisibility(uiOptions); } @@ -343,10 +336,10 @@ public class CordovaActivity extends Activity { * Called when an activity you launched exits, giving you the requestCode you started it with, * the resultCode it returned, and any additional data from it. * - * @param requestCode The request code originally supplied to startActivityForResult(), - * allowing you to identify who this result came from. - * @param resultCode The integer result code returned by the child activity through its setResult(). - * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). + * @param requestCode The request code originally supplied to startActivityForResult(), + * allowing you to identify who this result came from. + * @param resultCode The integer result code returned by the child activity through its setResult(). + * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { @@ -359,9 +352,9 @@ public class CordovaActivity extends Activity { * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable). * The errorCode parameter corresponds to one of the ERROR_* constants. * - * @param errorCode The error code corresponding to an ERROR_* value. - * @param description A String describing the error. - * @param failingUrl The url that failed to load. + * @param errorCode The error code corresponding to an ERROR_* value. + * @param description A String describing the error. + * @param failingUrl The url that failed to load. */ public void onReceivedError(final int errorCode, final String description, final String failingUrl) { final CordovaActivity me = this; @@ -450,9 +443,9 @@ public class CordovaActivity extends Activity { /** * Called when a message is sent to plugin. * - * @param id The message id - * @param data The message data - * @return Object or null + * @param id The message id + * @param data The message data + * @return Object or null */ public Object onMessage(String id, Object data) { if ("onReceivedError".equals(id)) { @@ -468,8 +461,7 @@ public class CordovaActivity extends Activity { return null; } - protected void onSaveInstanceState(Bundle outState) - { + protected void onSaveInstanceState(Bundle outState) { cordovaInterface.onSaveInstanceState(outState); super.onSaveInstanceState(outState); } @@ -477,7 +469,7 @@ public class CordovaActivity extends Activity { /** * Called by the system when the device configuration changes while your activity is running. * - * @param newConfig The new device configuration + * @param newConfig The new device configuration */ @Override public void onConfigurationChanged(Configuration newConfig) { @@ -490,4 +482,19 @@ public class CordovaActivity extends Activity { pm.onConfigurationChanged(newConfig); } } + + /** + * Called by the system when the user grants permissions + * + * @param requestCode + * @param permissions + * @param grantResults + */ + @Override + public void onRequestPermissionsResult(int requestCode, String permissions[], + int[] grantResults) { + PluginManager pm = this.appView.getPluginManager(); + pm.onRequestPermissionResult(requestCode, permissions, grantResults); + } + } diff --git a/framework/src/org/apache/cordova/CordovaInterface.java b/framework/src/org/apache/cordova/CordovaInterface.java index 59ed4864..3fa6e63b 100755 --- a/framework/src/org/apache/cordova/CordovaInterface.java +++ b/framework/src/org/apache/cordova/CordovaInterface.java @@ -69,4 +69,6 @@ public interface CordovaInterface { * Returns a shared thread pool that can be used for background tasks. */ public ExecutorService getThreadPool(); + + public void requestPermission(CordovaPlugin plugin); } diff --git a/framework/src/org/apache/cordova/CordovaInterfaceImpl.java b/framework/src/org/apache/cordova/CordovaInterfaceImpl.java index e35a181d..146bacb0 100644 --- a/framework/src/org/apache/cordova/CordovaInterfaceImpl.java +++ b/framework/src/org/apache/cordova/CordovaInterfaceImpl.java @@ -161,4 +161,10 @@ public class CordovaInterfaceImpl implements CordovaInterface { this.intent = intent; } } + + public void requestPermission(CordovaPlugin plugin) + { + pluginManager.requestPermission(plugin); + } + } diff --git a/framework/src/org/apache/cordova/CordovaPlugin.java b/framework/src/org/apache/cordova/CordovaPlugin.java index 7cf8528f..8ca1dd13 100644 --- a/framework/src/org/apache/cordova/CordovaPlugin.java +++ b/framework/src/org/apache/cordova/CordovaPlugin.java @@ -26,6 +26,7 @@ import org.json.JSONArray; import org.json.JSONException; import android.content.Intent; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.net.Uri; @@ -40,6 +41,7 @@ public class CordovaPlugin { public CordovaInterface cordova; protected CordovaPreferences preferences; private String serviceName; + private String [] permissions; /** * Call this after constructing to initialize the plugin. @@ -359,4 +361,50 @@ public class CordovaPlugin { */ public void onConfigurationChanged(Configuration newConfig) { } + + /** + * Called by the Plugin Manager when we need to actually request permissions + * + * @return Returns the permission that was stored in the plugin + */ + + public String[] getPermissionRequest() { + return permissions; + } + + /** + * requestPermission + */ + public void requestPermission() { + cordova.requestPermission(this); + } + + public boolean hasPermisssion() { + for(String p : permissions) + { + if(PackageManager.PERMISSION_DENIED == cordova.getActivity().checkSelfPermission(p)) + { + return false; + } + } + } + + /** + * Called by the system when the user grants permissions + * + * @param requestCode + * @param permissions + * @param grantResults + */ + public boolean onRequestPermissionResult(int requestCode, String[] permissions, + int[] grantResults) { + + for(int r:grantResults) + { + if(r == PackageManager.PERMISSION_DENIED) + return false; + } + + return true; + } } diff --git a/framework/src/org/apache/cordova/PluginManager.java b/framework/src/org/apache/cordova/PluginManager.java index a541e770..e543b04d 100755 --- a/framework/src/org/apache/cordova/PluginManager.java +++ b/framework/src/org/apache/cordova/PluginManager.java @@ -47,6 +47,8 @@ public class PluginManager { private final CordovaWebView app; private boolean isInitialized; + private CordovaPlugin permissionRequester; + public PluginManager(CordovaWebView cordovaWebView, CordovaInterface cordova, Collection pluginEntries) { this.ctx = cordova; this.app = cordovaWebView; @@ -508,4 +510,27 @@ public class PluginManager { } } } + + /** + * Called by the system when the user grants permissions + * + * @param requestCode + * @param permissions + * @param grantResults + */ + public void onRequestPermissionResult(int requestCode, String[] permissions, + int[] grantResults) { + if(permissionRequester != null) + { + permissionRequester.onRequestPermissionResult(requestCode, permissions, grantResults); + permissionRequester = null; + } + } + + public void requestPermission(CordovaPlugin plugin) { + permissionRequester = plugin; + String[] permissions = plugin.getPermissionRequest(); + int requestCode = 1; + ctx.getActivity().requestPermissions(permissions, requestCode); + } } diff --git a/framework/src/org/apache/cordova/engine/SystemWebChromeClient.java b/framework/src/org/apache/cordova/engine/SystemWebChromeClient.java index 3b5866c3..8c02bfa6 100755 --- a/framework/src/org/apache/cordova/engine/SystemWebChromeClient.java +++ b/framework/src/org/apache/cordova/engine/SystemWebChromeClient.java @@ -174,12 +174,21 @@ public class SystemWebChromeClient extends WebChromeClient { /** * Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin. * + * This also checks for the Geolocation Plugin and requests permission from the application to use Geolocation. + * * @param origin * @param callback */ public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) { super.onGeolocationPermissionsShowPrompt(origin, callback); callback.invoke(origin, true, false); + //Get the plugin, it should be loaded + CordovaPlugin geolocation = parentEngine.pluginManager.getPlugin("org.apache.cordova.geolocation.PermissionHandler"); + if(geolocation != null && !geolocation.hasPermisssion()) + { + parentEngine.pluginManager.requestPermission(geolocation); + } + } // API level 7 is required for this, see if we could lower this using something else