dpa99c / cordova-custom-config

Cordova/Phonegap plugin to update platform configuration files based on preferences and config-file data defined in config.xml
318 stars 84 forks source link

Removing Android permissions not working #107

Closed JarLowrey closed 7 years ago

JarLowrey commented 7 years ago

Adding the preference

<preference name="android-manifest/uses-permission/[@android:name='android.permission.WRITE_EXTERNAL_STORAGE']" delete="true" />

among others, does not have any effect. When building, the AndroidManifest is regenerated and the permissions re-appear. I have tried deleting all platforms and plugins, re-adding the android platform and running cordova prepare to re-download the plugins.

You can see my entire config.xml here. Thanks!

dpa99c commented 7 years ago

In isolation, the operation to remove that element works fine:

console output ``` $ more config.xml Custom config plugin example $ more platforms/android/AndroidManifest.xml $ cordova prepare android --verbose Executing script found in plugin cordova-custom-config for hook "before_prepare": plugins\cordova-custom-config\hooks\restoreBackups.js Resolving module name for q => q Resolving module name for path => path cordova-custom-config: Running restoreBackups.js cordova-custom-config: Loaded module dependencies cordova-custom-config: Skipping auto-restore of config file backup(s) Checking config.xml for saved platforms that haven't been added to the project Checking for any plugins added to the project that have not been installed in android platform No differences found between plugins added to project and installed in android platform. Continuing... Generating platform-specific config.xml from defaults for android at D:\Git\cordova-custom-config-example\platforms\android\res\xml\config.xml Merging project's config.xml into platform-specific android config.xml Merging and updating files from [www, platforms\android\platform_www] to platforms\android\assets\www Wrote out android application name "Custom config plugin example" to D:\Git\cordova-custom-config-example\platforms\android\res\values\strings.xml android-versionCode not found in config.xml. Generating a code based on version in config.xml (0.0.1): 1 Wrote out Android package name "uk.co.workingedge.phonegap.plugins.example.customconfig" to D:\Git\cordova-custom-config-example\platforms\android\src\uk\co\workingedge\phonegap\plugins\example\customconfig\MainActivity.java This app does not have launcher icons defined This app does not have splash screens defined Prepared android project successfully Executing script found in plugin cordova-custom-config for hook "after_prepare": plugins\cordova-custom-config\hooks\applyCustomConfig.js Resolving module name for q => q Resolving module name for path => path cordova-custom-config: Running applyCustomConfig.js cordova-custom-config: Loaded module dependencies cordova-custom-config: Backup exists for 'AndroidManifest.xml' at: D:\Git\cordova-custom-config-example\plugins\cordova-custom-config\backup\android\AndroidManifest.xml cordova-custom-config: Applied custom config from config.xml to D:\Git\cordova-custom-config-example\platforms\android\AndroidManifest.xml cordova-custom-config: Finished applying platform config Checking config.xml for saved plugins that haven't been added to the project $ more platforms/android/AndroidManifest.xml ```

However, while the plugin can remove config elements using <preference delete="true" /> syntax, it can't prevent other plugins adding it, which is what's happening in your case:

You are including cordova-plugin-x-socialsharing in your project which adds the WRITE_EXTERNAL_STORAGE permission in its plugin.xml.

Due to the way the Cordova CLI lifecycle works, if a plugin listed in the config.xml is missing from the plugins/ folder (e.g. in a CI environment where they are installed fresh every time), Cordova will install those plugins after any after_prepare hook scripts have finished execution (i.e. this plugin). Therefore, this plugin is actually removing the element, but the social sharing plugin is re-adding it again:

console output ``` $ more config.xml Custom config plugin example $ more platforms/android/AndroidManifest.xml $ cordova prepare android --verbose Executing script found in plugin cordova-custom-config for hook "before_prepare": plugins\cordova-custom-config\hooks\restoreBackups.js Resolving module name for q => q Resolving module name for path => path cordova-custom-config: Running restoreBackups.js cordova-custom-config: Loaded module dependencies cordova-custom-config: Skipping auto-restore of config file backup(s) Checking config.xml for saved platforms that haven't been added to the project Checking for any plugins added to the project that have not been installed in android platform No differences found between plugins added to project and installed in android platform. Continuing... Generating platform-specific config.xml from defaults for android at D:\Git\cordova-custom-config-example\platforms\android\res\xml\config.xml Merging project's config.xml into platform-specific android config.xml Merging and updating files from [www, platforms\android\platform_www] to platforms\android\assets\www copy platforms\android\platform_www\cordova_plugins.js platforms\android\assets\www\cordova_plugins.js (updated file) Wrote out android application name "Custom config plugin example" to D:\Git\cordova-custom-config-example\platforms\android\res\values\strings.xml android-versionCode not found in config.xml. Generating a code based on version in config.xml (0.0.1): 1 Wrote out Android package name "uk.co.workingedge.phonegap.plugins.example.customconfig" to D:\Git\cordova-custom-config-example\platforms\android\src\uk\co\workingedge\phonegap\plugins\example\customconfig\MainActivity.java This app does not have launcher icons defined This app does not have splash screens defined Prepared android project successfully Executing script found in plugin cordova-custom-config for hook "after_prepare": plugins\cordova-custom-config\hooks\applyCustomConfig.js Resolving module name for q => q Resolving module name for path => path cordova-custom-config: Running applyCustomConfig.js cordova-custom-config: Loaded module dependencies cordova-custom-config: Backup exists for 'AndroidManifest.xml' at: D:\Git\cordova-custom-config-example\plugins\cordova-custom-config\backup\android\AndroidManifest.xml cordova-custom-config: Applied custom config from config.xml to D:\Git\cordova-custom-config-example\platforms\android\AndroidManifest.xml cordova-custom-config: Finished applying platform config Checking config.xml for saved plugins that haven't been added to the project Discovered plugin "cordova-plugin-x-socialsharing" in config.xml. Adding it to the project No scripts found for hook "before_plugin_add". Calling plugman.fetch on plugin "cordova-plugin-x-socialsharing@~5.1.6" Fetching plugin "cordova-plugin-x-socialsharing@~5.1.6" via npm Copying plugin "G:\Users\dpa99_000\.cordova\lib\npm_cache\cordova-plugin-x-socialsharing\5.1.6\package" => "D:\Git\cordova-custom-config-example\plugins\cordova-plugin-x-socialsharing" Calling plugman.install on plugin "D:\Git\cordova-custom-config-example\plugins\cordova-plugin-x-socialsharing" for platform "android Installing "cordova-plugin-x-socialsharing" for android Running command: cmd "/s /c "D:\Git\cordova-custom-config-example\platforms\android\cordova\version.bat"" Command finished with error code 0: cmd /s /c "D:\Git\cordova-custom-config-example\platforms\android\cordova\version.bat" Finding scripts for "before_plugin_install" hook from plugin cordova-plugin-x-socialsharing on android platform only. No scripts found for hook "before_plugin_install". Install start for "cordova-plugin-x-socialsharing" on android. ANDROID_HOME=G:\Users\dpa99_000\AppData\Local\Android\sdk JAVA_HOME=C:\Program Files\Java\jdk1.8.0_31 Subproject Path: CordovaLib Running command: cmd "/s /c "D:\Git\cordova-custom-config-example\platforms\android\gradlew.bat clean -b D:\Git\cordova-custom-config-example\platforms\android\build.gradle -Dorg.gradle.daemon=true -Dorg.gradle.jvmargs=-Xmx2048m -Pandroid.useDeprecatedNdk=true"" Parallel execution with configuration on demand is an incubating feature. The Task.leftShift(Closure) method has been deprecated and is scheduled to be removed in Gradle 5.0. Please use Task.doLast(Action) instead. at build_3z2n1etrm7pu5n18bejmtste4.run(D:\Git\cordova-custom-config-example\platforms\android\build.gradle:137) The JavaCompile.setDependencyCacheDir() method has been deprecated and is scheduled to be removed in Gradle 4.0. The TaskInputs.source(Object) method has been deprecated and is scheduled to be removed in Gradle 4.0. Please use TaskInputs.file(Object).skipWhenEmpty() instead. The ProjectDependency.getProjectConfiguration() method has been deprecated and is scheduled to be removed in Gradle 4.0. ModuleDependency.getConfiguration() has been deprecated and is scheduled to be removed in Gradle 4.0. Use ModuleDependency.getTargetConfiguration() instead. :clean :CordovaLib:clean BUILD SUCCESSFUL Total time: 1.554 secs Command finished with error code 0: cmd /s /c "D:\Git\cordova-custom-config-example\platforms\android\gradlew.bat clean -b D:\Git\cordova-custom-config-example\platforms\android\build.gradle -Dorg.gradle.daemon=true -Dorg.gradle.jvmargs=-Xmx2048m -Pandroid.useDeprecatedNdk=true" Beginning processing of action stack for android project... Installing Android library: com.android.support:support-v4:24.1.1+ Action stack processing complete. Updating build files since android plugin contained Subproject Path: CordovaLib Install complete for cordova-plugin-x-socialsharing on android. Finding scripts for "after_plugin_install" hook from plugin cordova-plugin-x-socialsharing on android platform only. No scripts found for hook "after_plugin_install". No scripts found for hook "after_plugin_add". $ more platforms/android/AndroidManifest.xml ```

However, once the plugin is present in the local project, subsequent prepare operations will not re-invoke its installation and therefore not re-add its config:

console output ``` $ cordova plugin ls cordova-custom-config 3.0.14 "cordova-custom-config" cordova-plugin-whitelist 1.0.0 "Whitelist" cordova-plugin-x-socialsharing 5.1.6 "SocialSharing" $ more config.xml Custom config plugin example $ more platforms/android/AndroidManifest.xml $ cordova prepare android --verbose Executing script found in plugin cordova-custom-config for hook "before_prepare": plugins\cordova-custom-config\hooks\restoreBackups.js Resolving module name for q => q Resolving module name for path => path cordova-custom-config: Running restoreBackups.js cordova-custom-config: Loaded module dependencies cordova-custom-config: Skipping auto-restore of config file backup(s) Checking config.xml for saved platforms that haven't been added to the project Checking for any plugins added to the project that have not been installed in android platform No differences found between plugins added to project and installed in android platform. Continuing... Generating platform-specific config.xml from defaults for android at D:\Git\cordova-custom-config-example\platforms\android\res\xml\config.xml Merging project's config.xml into platform-specific android config.xml Merging and updating files from [www, platforms\android\platform_www] to platforms\android\assets\www copy platforms\android\platform_www\cordova_plugins.js platforms\android\assets\www\cordova_plugins.js (updated file) copy platforms\android\platform_www\plugins\cordova-plugin-x-socialsharing\www\SocialSharing.js platforms\android\assets\www\plugins\cordova-plugin-x-socialsharing\www\SocialSharing.js (updated file) Wrote out android application name "Custom config plugin example" to D:\Git\cordova-custom-config-example\platforms\android\res\values\strings.xml android-versionCode not found in config.xml. Generating a code based on version in config.xml (0.0.1): 1 Wrote out Android package name "uk.co.workingedge.phonegap.plugins.example.customconfig" to D:\Git\cordova-custom-config-example\platforms\android\src\uk\co\workingedge\phonegap\plugins\example\customconfig\MainActivity.java This app does not have launcher icons defined This app does not have splash screens defined Prepared android project successfully Executing script found in plugin cordova-custom-config for hook "after_prepare": plugins\cordova-custom-config\hooks\applyCustomConfig.js Resolving module name for q => q Resolving module name for path => path cordova-custom-config: Running applyCustomConfig.js cordova-custom-config: Loaded module dependencies cordova-custom-config: Backup exists for 'AndroidManifest.xml' at: D:\Git\cordova-custom-config-example\plugins\cordova-custom-config\backup\android\AndroidManifest.xml cordova-custom-config: Applied custom config from config.xml to D:\Git\cordova-custom-config-example\platforms\android\AndroidManifest.xml cordova-custom-config: Finished applying platform config Checking config.xml for saved plugins that haven't been added to the project $ more platforms/android/AndroidManifest.xml ```

If you really need to remove this permission (I'm not sure why this would be essential) and you are unable to build in a local environment where the locally installed plugins persist, you could fork the social sharing plugin in order to remove that preference from its plugin.xml to prevent it being added to the AndroidManifest.xml each time the plugin is installed.

JarLowrey commented 7 years ago

I'm just trying to remove as many permissions as possible, I don't want that to be a barrier to downloading.

This was an awesome response, thank you! If I understand you correctly, the solution would be to manually edit my local plugins to prevent the addition of those permissions and then subsequent builds will not overwrite the changes via a download or anything. Does that sound about right?

dpa99c commented 7 years ago

Yes, either edit the plugins locally or fork the Github repo, edit and push changes, then add the modified plugin to your project direct from your Github forked repo. The latter will prevent your local edits being overwritten.

JarLowrey commented 7 years ago

Hey thanks much @dpa99c, it's much appreciated. I found references for which permissions user's are alerted about at this SO post, which references this file which lists out 'dangerous' permissions in the Android source code.

If you happen to know, what is the point of having this delete="true" ability for permissions? If it will never work to fully remove the permissions (ie, the solution is always to edit local plugins due to the CLI lifecycle) why is it helpful? Or does it work in some scenarios? Is there any way to write hooks/scripts that integrate to Cordova CLI life cycle that prevent modifying local packages or forking plugin repos? That seems exceptionally burdensome, it's kind of unbelievable to me Cordova doesn't have a better method for this. Thanks much!

JarLowrey commented 7 years ago

I edited all the plugins plugins.xml locally, reran cordova prepare and rebuilt the app, but all the permissions were still auto-added to AndroidManifest.xml. I then also edited platforms/android.json, I guess because a previous build added the plugin permissions there but permissions still remain...

It seems like there are a million ways to go wrong here, and this is the only way to do it?

dpa99c commented 7 years ago

If you happen to know, what is the point of having this delete="true" ability for permissions?

As the output in my comments above illustrates, if the plugin is present locally, then the plugin config should not be re-applied on subsequent build/prepare operations (only on plugin_install). In which case, delete=true functions as expected to remove config added by plugins when they were installed on the next prepare operation.

Run cordova prepare --verbose to see detailed output of the order of operations in order to understand the Cordova CLI lifecycle.

JarLowrey commented 7 years ago

Hey thanks again @dpa99c . Running cordova prepare --verbose showed that the Android Manifest was not being rebuilt using the new local plugin info, but instead was restoring from plugins/cordova-custom-config/backup/android/AndroidManifest.xml. I deleted that file and re-ran prepare and the permissions are updated! Is there a way to ignore the backup/why is a backup being saved?

dpa99c commented 7 years ago

Unless you are using a really old version of the plugin, auto-backup behaviour is turned off by default unless you explicitly enable it - see here.

The reason for having this option is that you can experiment with various custom configs in your config.xml and have them removed by restoring the original AndroidManifest.xml. Otherwise, you'd have to manually remove the changes. See here.

JarLowrey commented 7 years ago

That's interesting, thanks for the references. I have the newest version - 3.0.14, and no autorestore property in my config.xml, but the backup file keeps getting made. Not sure why.

dpa99c commented 7 years ago

Have a look at the example project which contains unit test for the plugin. You can run the locally with npm test. Hmm just noticed the CI tests are failing, but that's due to a dependency of CI environment setup.

JarLowrey commented 7 years ago

Just cloned the example project, added android and ios platforms, and ran cordova prepare and npm test. All tests passed, but the backup folder is created. Inside of the backup folder are android/AndroidManifest.xml and ios/* where * is a lot of stuff.

In that example project autorestore="false" in config.xml.

dpa99c commented 7 years ago

Backup folder is created but not restored unless autorestore is true. Set to false is same as omitting it. Try it.

dpa99c commented 7 years ago

Closed due to no response from OP