You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by no...@apache.org on 2021/03/27 15:17:48 UTC
[cordova-android] branch master updated: Fix for #924 - Concurrent
Modification Exception (#1091)
This is an automated email from the ASF dual-hosted git repository.
normanbreau pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cordova-android.git
The following commit(s) were added to refs/heads/master by this push:
new 9dcf3eb Fix for #924 - Concurrent Modification Exception (#1091)
9dcf3eb is described below
commit 9dcf3eb68b5a985c2470e8e9781255b8311bd70b
Author: ebhsgit <48...@users.noreply.github.com>
AuthorDate: Sun Mar 28 02:17:39 2021 +1100
Fix for #924 - Concurrent Modification Exception (#1091)
Co-authored-by: 8bhsolutions <48...@users.noreply.github.com>
---
.../src/org/apache/cordova/PluginManager.java | 211 +++++++++++++--------
1 file changed, 128 insertions(+), 83 deletions(-)
diff --git a/framework/src/org/apache/cordova/PluginManager.java b/framework/src/org/apache/cordova/PluginManager.java
index c9576a6..f7a2e41 100755
--- a/framework/src/org/apache/cordova/PluginManager.java
+++ b/framework/src/org/apache/cordova/PluginManager.java
@@ -19,7 +19,9 @@
package org.apache.cordova;
import java.util.Collection;
+import java.util.Collections;
import java.util.LinkedHashMap;
+import java.util.Map;
import org.json.JSONException;
@@ -40,8 +42,8 @@ public class PluginManager {
private static final int SLOW_EXEC_WARNING_THRESHOLD = Debug.isDebuggerConnected() ? 60 : 16;
// List of service entries
- private final LinkedHashMap<String, CordovaPlugin> pluginMap = new LinkedHashMap<String, CordovaPlugin>();
- private final LinkedHashMap<String, PluginEntry> entryMap = new LinkedHashMap<String, PluginEntry>();
+ private final Map<String, CordovaPlugin> pluginMap = Collections.synchronizedMap(new LinkedHashMap<String, CordovaPlugin>());
+ private final Map<String, PluginEntry> entryMap = Collections.synchronizedMap(new LinkedHashMap<String, PluginEntry>());
private final CordovaInterface ctx;
private final CordovaWebView app;
@@ -90,13 +92,17 @@ public class PluginManager {
* Create plugins objects that have onload set.
*/
private void startupPlugins() {
- for (PluginEntry entry : entryMap.values()) {
- // Add a null entry to for each non-startup plugin to avoid ConcurrentModificationException
- // When iterating plugins.
- if (entry.onload) {
- getPlugin(entry.service);
- } else {
- pluginMap.put(entry.service, null);
+ synchronized (entryMap) {
+ for (PluginEntry entry : entryMap.values()) {
+ // Add a null entry to for each non-startup plugin to avoid ConcurrentModificationException
+ // When iterating plugins.
+ if (entry.onload) {
+ getPlugin(entry.service);
+ }
+ else {
+ LOG.d(TAG, "startupPlugins: put - " + entry.service);
+ pluginMap.put(entry.service, null);
+ }
}
}
}
@@ -169,6 +175,7 @@ public class PluginManager {
ret = instantiatePlugin(pe.pluginClass);
}
ret.privateInitialize(service, ctx, app, app.getPreferences());
+ LOG.d(TAG, "getPlugin - put: " + service);
pluginMap.put(service, ret);
}
return ret;
@@ -196,6 +203,7 @@ public class PluginManager {
this.entryMap.put(entry.service, entry);
if (entry.plugin != null) {
entry.plugin.privateInitialize(entry.service, ctx, app, app.getPreferences());
+ LOG.d(TAG, "addService: put - " + entry.service);
pluginMap.put(entry.service, entry.plugin);
}
}
@@ -206,9 +214,11 @@ public class PluginManager {
* @param multitasking Flag indicating if multitasking is turned on for app
*/
public void onPause(boolean multitasking) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onPause(multitasking);
+ synchronized (this.pluginMap) {
+ for (CordovaPlugin plugin : this.pluginMap.values()) {
+ if (plugin != null) {
+ plugin.onPause(multitasking);
+ }
}
}
}
@@ -226,9 +236,11 @@ public class PluginManager {
*
*/
public boolean onReceivedHttpAuthRequest(CordovaWebView view, ICordovaHttpAuthHandler handler, String host, String realm) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null && plugin.onReceivedHttpAuthRequest(app, handler, host, realm)) {
- return true;
+ synchronized (this.pluginMap) {
+ for (CordovaPlugin plugin : this.pluginMap.values()) {
+ if (plugin != null && plugin.onReceivedHttpAuthRequest(app, handler, host, realm)) {
+ return true;
+ }
}
}
return false;
@@ -245,9 +257,11 @@ public class PluginManager {
*
*/
public boolean onReceivedClientCertRequest(CordovaWebView view, ICordovaClientCertRequest request) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null && plugin.onReceivedClientCertRequest(app, request)) {
- return true;
+ synchronized (this.pluginMap) {
+ for (CordovaPlugin plugin : this.pluginMap.values()) {
+ if (plugin != null && plugin.onReceivedClientCertRequest(app, request)) {
+ return true;
+ }
}
}
return false;
@@ -259,9 +273,11 @@ public class PluginManager {
* @param multitasking Flag indicating if multitasking is turned on for app
*/
public void onResume(boolean multitasking) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onResume(multitasking);
+ synchronized (this.pluginMap) {
+ for (CordovaPlugin plugin : this.pluginMap.values()) {
+ if (plugin != null) {
+ plugin.onResume(multitasking);
+ }
}
}
}
@@ -270,9 +286,11 @@ public class PluginManager {
* Called when the activity is becoming visible to the user.
*/
public void onStart() {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onStart();
+ synchronized (this.pluginMap) {
+ for (CordovaPlugin plugin : this.pluginMap.values()) {
+ if (plugin != null) {
+ plugin.onStart();
+ }
}
}
}
@@ -281,9 +299,11 @@ public class PluginManager {
* Called when the activity is no longer visible to the user.
*/
public void onStop() {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onStop();
+ synchronized (this.pluginMap) {
+ for (CordovaPlugin plugin : this.pluginMap.values()) {
+ if (plugin != null) {
+ plugin.onStop();
+ }
}
}
}
@@ -292,9 +312,11 @@ public class PluginManager {
* The final call you receive before your activity is destroyed.
*/
public void onDestroy() {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onDestroy();
+ synchronized (this.pluginMap) {
+ for (CordovaPlugin plugin : this.pluginMap.values()) {
+ if (plugin != null) {
+ plugin.onDestroy();
+ }
}
}
}
@@ -307,11 +329,14 @@ public class PluginManager {
* @return Object to stop propagation or null
*/
public Object postMessage(String id, Object data) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- Object obj = plugin.onMessage(id, data);
- if (obj != null) {
- return obj;
+ LOG.d(TAG, "postMessage: " + id);
+ synchronized (this.pluginMap) {
+ for (CordovaPlugin plugin : this.pluginMap.values()) {
+ if (plugin != null) {
+ Object obj = plugin.onMessage(id, data);
+ if (obj != null) {
+ return obj;
+ }
}
}
}
@@ -322,9 +347,11 @@ public class PluginManager {
* Called when the activity receives a new intent.
*/
public void onNewIntent(Intent intent) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onNewIntent(intent);
+ synchronized (this.pluginMap) {
+ for (CordovaPlugin plugin : this.pluginMap.values()) {
+ if (plugin != null) {
+ plugin.onNewIntent(intent);
+ }
}
}
}
@@ -341,12 +368,14 @@ public class PluginManager {
* false to block the resource.
*/
public boolean shouldAllowRequest(String url) {
- for (PluginEntry entry : this.entryMap.values()) {
- CordovaPlugin plugin = pluginMap.get(entry.service);
- if (plugin != null) {
- Boolean result = plugin.shouldAllowRequest(url);
- if (result != null) {
- return result;
+ synchronized (this.entryMap) {
+ for (PluginEntry entry : this.entryMap.values()) {
+ CordovaPlugin plugin = pluginMap.get(entry.service);
+ if (plugin != null) {
+ Boolean result = plugin.shouldAllowRequest(url);
+ if (result != null) {
+ return result;
+ }
}
}
}
@@ -379,12 +408,14 @@ public class PluginManager {
* false to block the navigation.
*/
public boolean shouldAllowNavigation(String url) {
- for (PluginEntry entry : this.entryMap.values()) {
- CordovaPlugin plugin = pluginMap.get(entry.service);
- if (plugin != null) {
- Boolean result = plugin.shouldAllowNavigation(url);
- if (result != null) {
- return result;
+ synchronized (this.entryMap) {
+ for (PluginEntry entry : this.entryMap.values()) {
+ CordovaPlugin plugin = pluginMap.get(entry.service);
+ if (plugin != null) {
+ Boolean result = plugin.shouldAllowNavigation(url);
+ if (result != null) {
+ return result;
+ }
}
}
}
@@ -398,12 +429,14 @@ public class PluginManager {
* Called when the webview is requesting the exec() bridge be enabled.
*/
public boolean shouldAllowBridgeAccess(String url) {
- for (PluginEntry entry : this.entryMap.values()) {
- CordovaPlugin plugin = pluginMap.get(entry.service);
- if (plugin != null) {
- Boolean result = plugin.shouldAllowBridgeAccess(url);
- if (result != null) {
- return result;
+ synchronized (this.entryMap) {
+ for (PluginEntry entry : this.entryMap.values()) {
+ CordovaPlugin plugin = pluginMap.get(entry.service);
+ if (plugin != null) {
+ Boolean result = plugin.shouldAllowBridgeAccess(url);
+ if (result != null) {
+ return result;
+ }
}
}
}
@@ -425,12 +458,14 @@ public class PluginManager {
* false to block the intent.
*/
public Boolean shouldOpenExternalUrl(String url) {
- for (PluginEntry entry : this.entryMap.values()) {
- CordovaPlugin plugin = pluginMap.get(entry.service);
- if (plugin != null) {
- Boolean result = plugin.shouldOpenExternalUrl(url);
- if (result != null) {
- return result;
+ synchronized (this.entryMap) {
+ for (PluginEntry entry : this.entryMap.values()) {
+ CordovaPlugin plugin = pluginMap.get(entry.service);
+ if (plugin != null) {
+ Boolean result = plugin.shouldOpenExternalUrl(url);
+ if (result != null) {
+ return result;
+ }
}
}
}
@@ -446,32 +481,38 @@ public class PluginManager {
* @return Return false to allow the URL to load, return true to prevent the URL from loading.
*/
public boolean onOverrideUrlLoading(String url) {
- for (PluginEntry entry : this.entryMap.values()) {
- CordovaPlugin plugin = pluginMap.get(entry.service);
- if (plugin != null && plugin.onOverrideUrlLoading(url)) {
- return true;
+ synchronized (this.entryMap) {
+ for (PluginEntry entry : this.entryMap.values()) {
+ CordovaPlugin plugin = pluginMap.get(entry.service);
+ if (plugin != null && plugin.onOverrideUrlLoading(url)) {
+ return true;
+ }
}
+ return false;
}
- return false;
}
/**
* Called when the app navigates or refreshes.
*/
public void onReset() {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onReset();
+ synchronized (this.pluginMap) {
+ for (CordovaPlugin plugin : this.pluginMap.values()) {
+ if (plugin != null) {
+ plugin.onReset();
+ }
}
}
}
Uri remapUri(Uri uri) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- Uri ret = plugin.remapUri(uri);
- if (ret != null) {
- return ret;
+ synchronized (this.pluginMap) {
+ for (CordovaPlugin plugin : this.pluginMap.values()) {
+ if (plugin != null) {
+ Uri ret = plugin.remapUri(uri);
+ if (ret != null) {
+ return ret;
+ }
}
}
}
@@ -504,20 +545,24 @@ public class PluginManager {
* @param newConfig The new device configuration
*/
public void onConfigurationChanged(Configuration newConfig) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onConfigurationChanged(newConfig);
+ synchronized (this.pluginMap) {
+ for (CordovaPlugin plugin : this.pluginMap.values()) {
+ if (plugin != null) {
+ plugin.onConfigurationChanged(newConfig);
+ }
}
}
}
public Bundle onSaveInstanceState() {
Bundle state = new Bundle();
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- Bundle pluginState = plugin.onSaveInstanceState();
- if(pluginState != null) {
- state.putBundle(plugin.getServiceName(), pluginState);
+ synchronized (this.pluginMap) {
+ for (CordovaPlugin plugin : this.pluginMap.values()) {
+ if (plugin != null) {
+ Bundle pluginState = plugin.onSaveInstanceState();
+ if (pluginState != null) {
+ state.putBundle(plugin.getServiceName(), pluginState);
+ }
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org