Index: components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java |
diff --git a/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java b/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java |
index 345692dc565c1e8efbbb3e1241d0c14a3e41c3bf..50b02275104a449126ea04d188265ecee621242c 100644 |
--- a/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java |
+++ b/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java |
@@ -22,6 +22,7 @@ import org.chromium.net.BidirectionalStream; |
import org.chromium.net.CronetEngine; |
import org.chromium.net.NetworkQualityRttListener; |
import org.chromium.net.NetworkQualityThroughputListener; |
+import org.chromium.net.RequestFinishedListener; |
import org.chromium.net.UrlRequest; |
import org.chromium.net.urlconnection.CronetHttpURLConnection; |
import org.chromium.net.urlconnection.CronetURLStreamHandlerFactory; |
@@ -30,6 +31,7 @@ import java.net.Proxy; |
import java.net.URL; |
import java.net.URLConnection; |
import java.net.URLStreamHandlerFactory; |
+import java.util.ArrayList; |
import java.util.Collection; |
import java.util.List; |
import java.util.Map; |
@@ -64,11 +66,18 @@ public class CronetUrlRequestContext extends CronetEngine { |
private Executor mNetworkQualityExecutor; |
private boolean mNetworkQualityEstimatorEnabled; |
- /** Locks operations on network quality listeners, because listener |
+ /** |
+ * Locks operations on network quality listeners, because listener |
* addition and removal may occur on a different thread from notification. |
*/ |
private final Object mNetworkQualityLock = new Object(); |
+ /** |
+ * Locks operations on the list of RequestFinishedListeners, because operations can happen on |
+ * any thread. |
+ */ |
+ private final Object mFinishedListenerLock = new Object(); |
+ |
@GuardedBy("mNetworkQualityLock") |
private final ObserverList<NetworkQualityRttListener> mRttListenerList = |
new ObserverList<NetworkQualityRttListener>(); |
@@ -77,9 +86,9 @@ public class CronetUrlRequestContext extends CronetEngine { |
private final ObserverList<NetworkQualityThroughputListener> mThroughputListenerList = |
new ObserverList<NetworkQualityThroughputListener>(); |
- @GuardedBy("mNetworkQualityLock") |
- private final ObserverList<RequestFinishedListener> mFinishedListenerList = |
- new ObserverList<RequestFinishedListener>(); |
+ @GuardedBy("mFinishedListenerLock") |
+ private final List<RequestFinishedListener> mFinishedListenerList = |
+ new ArrayList<RequestFinishedListener>(); |
/** |
* Synchronize access to mCertVerifierData. |
@@ -153,11 +162,9 @@ public class CronetUrlRequestContext extends CronetEngine { |
boolean disableConnectionMigration) { |
synchronized (mLock) { |
checkHaveAdapter(); |
- boolean metricsCollectionEnabled = mNetworkQualityEstimatorEnabled; |
- if (metricsCollectionEnabled) { // Collect metrics only if someone is listening. |
- synchronized (mNetworkQualityLock) { |
- metricsCollectionEnabled = !mFinishedListenerList.isEmpty(); |
- } |
+ boolean metricsCollectionEnabled = false; |
+ synchronized (mFinishedListenerLock) { |
+ metricsCollectionEnabled = !mFinishedListenerList.isEmpty(); |
} |
return new CronetUrlRequest(this, url, priority, callback, executor, requestAnnotations, |
metricsCollectionEnabled, disableCache, disableConnectionMigration); |
@@ -379,15 +386,8 @@ public class CronetUrlRequestContext extends CronetEngine { |
*/ |
@Override |
public void addRequestFinishedListener(RequestFinishedListener listener) { |
- if (!mNetworkQualityEstimatorEnabled) { |
- throw new IllegalStateException("Network quality estimator must be enabled"); |
- } |
- // RequestFinishedListener does not provide its own executor. |
- if (mNetworkQualityExecutor == null) { |
- throw new IllegalStateException("Executor must not be null"); |
- } |
- synchronized (mNetworkQualityLock) { |
- mFinishedListenerList.addObserver(listener); |
+ synchronized (mFinishedListenerLock) { |
+ mFinishedListenerList.add(listener); |
} |
} |
@@ -396,11 +396,8 @@ public class CronetUrlRequestContext extends CronetEngine { |
*/ |
@Override |
public void removeRequestFinishedListener(RequestFinishedListener listener) { |
- if (!mNetworkQualityEstimatorEnabled) { |
- throw new IllegalStateException("Network quality estimator must be enabled"); |
- } |
- synchronized (mNetworkQualityLock) { |
- mFinishedListenerList.removeObserver(listener); |
+ synchronized (mFinishedListenerLock) { |
+ mFinishedListenerList.remove(listener); |
} |
} |
@@ -528,30 +525,20 @@ public class CronetUrlRequestContext extends CronetEngine { |
} |
void reportFinished(final CronetUrlRequest request) { |
- if (!mNetworkQualityEstimatorEnabled) { |
- return; |
- } |
- // If no request finished listener has been added, then mNetworkQualityExecutor may be |
- // null. Exit early to avoid posting to a null executor. |
- synchronized (mNetworkQualityLock) { |
- if (mFinishedListenerList.isEmpty()) { |
- return; |
- } |
- } |
- Runnable task = new Runnable() { |
- @Override |
- public void run() { |
- synchronized (mNetworkQualityLock) { |
- UrlRequestInfo requestInfo = request.getRequestInfo(); |
- for (RequestFinishedListener listener : mFinishedListenerList) { |
- listener.onRequestFinished(requestInfo); |
- } |
+ final UrlRequestInfo requestInfo = request.getRequestInfo(); |
+ ArrayList<RequestFinishedListener> currentListeners; |
+ synchronized (mFinishedListenerLock) { |
+ currentListeners = new ArrayList<RequestFinishedListener>(mFinishedListenerList); |
+ } |
+ for (final RequestFinishedListener listener : currentListeners) { |
+ Runnable task = new Runnable() { |
+ @Override |
+ public void run() { |
+ listener.onRequestFinished(requestInfo); |
} |
- } |
- }; |
- // Use {@link mNetworkQualityExecutor} since |
- // RequestFInishedListeners do not provide an executor. |
- postObservationTaskToExecutor(mNetworkQualityExecutor, task); |
+ }; |
+ postObservationTaskToExecutor(listener.getExecutor(), task); |
+ } |
} |
private static void postObservationTaskToExecutor(Executor executor, Runnable task) { |