Chromium Code Reviews| 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..b9ab56c81b18844bd34ebe14ae963e54a3b34404 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; |
| @@ -69,6 +71,11 @@ public class CronetUrlRequestContext extends CronetEngine { |
| */ |
| private final Object mNetworkQualityLock = new Object(); |
| + /** Locks operations on the list of RequestFinishedListeners, because operations can happen on |
|
xunjieli
2016/07/29 16:35:25
The previous example is a bad example :(
The firs
mgersh
2016/07/29 18:21:52
Done.
|
| + * any thread. |
| + */ |
| + private final Object mFinishedListenerLock = new Object(); |
| + |
| @GuardedBy("mNetworkQualityLock") |
| private final ObserverList<NetworkQualityRttListener> mRttListenerList = |
| new ObserverList<NetworkQualityRttListener>(); |
| @@ -77,9 +84,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 +160,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 +384,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 +394,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 +523,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) { |