Chromium Code Reviews| Index: components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java |
| diff --git a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java |
| index 4c7afc6c0f2278fc2be06da86220681d7d2ee5ac..aaa25fd0657d2e1e23bbca1d7210d1c55ef722a4 100644 |
| --- a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java |
| +++ b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java |
| @@ -6,6 +6,9 @@ package org.chromium.net; |
| import android.content.Context; |
| import android.os.Build; |
| +import android.os.ConditionVariable; |
| +import android.os.Handler; |
| +import android.os.Looper; |
| import android.os.Process; |
| import android.util.Log; |
| @@ -25,29 +28,54 @@ public class CronetUrlRequestContext extends UrlRequestContext { |
| private static final int LOG_VERBOSE = -2; // LOG(FATAL...INFO), VLOG(2) |
| static final String LOG_TAG = "ChromiumNetwork"; |
| + /** |
| + * Synchronize access to mUrlRequestContextAdapter and shutdown routine. |
| + */ |
| + private final Object mLock = new Object(); |
| private long mUrlRequestContextAdapter = 0; |
| private Thread mNetworkThread; |
| + private final ConditionVariable mInitCompleted = new ConditionVariable(false); |
|
mmenke
2015/01/23 20:41:41
A couple lines in here that could be reformatted t
mef
2015/01/28 21:32:28
Acknowledged.
|
| + |
| private AtomicInteger mActiveRequestCount = new AtomicInteger(0); |
| public CronetUrlRequestContext(Context context, |
| UrlRequestContextConfig config) { |
| + CronetLibraryLoader.ensureInitialized(context, config); |
| nativeSetMinLogLevel(getLoggingLevel()); |
| mUrlRequestContextAdapter = nativeCreateRequestContextAdapter( |
| context, config.toString()); |
| if (mUrlRequestContextAdapter == 0) { |
| throw new NullPointerException("Context Adapter creation failed"); |
| } |
|
mmenke
2015/01/23 20:41:41
Suggest a blank line before a comment that applies
mef
2015/01/28 21:32:28
Done.
|
| + // Post a task to UI thread to init native Chromium URLRequestContext. |
| + // TODO(xunjieli): This constructor is not supposed to be invoked on |
| + // the main thread. Consider making the following code into a blocking |
| + // API to handle the case where we are already on main thread. |
|
mmenke
2015/01/23 20:41:41
Should be clearer here about what cases are bad.
mef
2015/01/28 21:32:28
Hrm, are they actually bad?
|
| + Runnable task = new Runnable() { |
| + public void run() { |
| + synchronized (mLock) { |
| + // mUrlRequestContextAdapter is guaranteed to exist until |
| + // initialization on main and network threads completes and |
| + // initNetworkThread is called back on network thread. |
| + nativeInitRequestContextOnMainThread(mUrlRequestContextAdapter); |
| + mInitCompleted.open(); |
| + } |
| + } |
| + }; |
| + new Handler(Looper.getMainLooper()).post(task); |
| } |
| @Override |
| public UrlRequest createRequest(String url, UrlRequestListener listener, |
| Executor executor) { |
| - if (mUrlRequestContextAdapter == 0) { |
| - throw new IllegalStateException( |
| - "Cannot create requests on shutdown context."); |
| + synchronized (mLock) { |
| + if (mUrlRequestContextAdapter == 0) { |
| + throw new IllegalStateException( |
| + "Context is shutdown."); |
|
mmenke
2015/01/23 20:41:41
Think this can fit on a single line.
mef
2015/01/28 21:32:28
Done.
|
| + } |
| + return new CronetUrlRequest(this, mUrlRequestContextAdapter, url, |
| + UrlRequest.REQUEST_PRIORITY_MEDIUM, listener, executor); |
| } |
| - return new CronetUrlRequest(this, mUrlRequestContextAdapter, url, |
| - UrlRequest.REQUEST_PRIORITY_MEDIUM, listener, executor); |
| } |
| @Override |
| @@ -62,28 +90,54 @@ public class CronetUrlRequestContext extends UrlRequestContext { |
| @Override |
| public void shutdown() { |
| - if (mActiveRequestCount.get() != 0) { |
| - throw new IllegalStateException( |
| - "Cannot shutdown with active requests."); |
| + synchronized (mLock) { |
|
mmenke
2015/01/23 20:41:41
Hrm...Still really not a fan of this. I'll see if
mef
2015/01/28 21:32:28
SG, let's chat tomorrow.
|
| + if (mUrlRequestContextAdapter == 0) { |
| + throw new IllegalStateException( |
| + "Context is already shutdown."); |
| + } |
| + if (mActiveRequestCount.get() != 0) { |
| + throw new IllegalStateException( |
| + "Cannot shutdown with active requests."); |
| + } |
| + // Destroying adapter stops the network thread, so it cannot be |
| + // called on network thread. |
| + if (Thread.currentThread() == mNetworkThread) { |
| + throw new IllegalThreadStateException( |
| + "Cannot shutdown from network thread."); |
| + } |
| } |
| - // Destroying adapter stops the network thread, so it cannot be called |
| - // on network thread. |
| - if (Thread.currentThread() == mNetworkThread) { |
| - throw new IllegalThreadStateException( |
| - "Cannot shutdown from network thread."); |
| + // Wait for init to complete on main thread (without lock, so main thread |
| + // could access it). |
| + mInitCompleted.block(); |
| + |
| + long urlRequestContextAdapter; |
| + synchronized (mLock) { |
| + urlRequestContextAdapter = mUrlRequestContextAdapter; |
| + mUrlRequestContextAdapter = 0; |
| } |
| - nativeDestroyRequestContextAdapter(mUrlRequestContextAdapter); |
| - mUrlRequestContextAdapter = 0; |
| + nativeDestroyRequestContextAdapter(urlRequestContextAdapter); |
| } |
| @Override |
| public void startNetLogToFile(String fileName) { |
| - nativeStartNetLogToFile(mUrlRequestContextAdapter, fileName); |
| + synchronized (mLock) { |
| + if (mUrlRequestContextAdapter == 0) { |
| + throw new IllegalStateException( |
| + "Context is shutdown."); |
| + } |
| + nativeStartNetLogToFile(mUrlRequestContextAdapter, fileName); |
| + } |
| } |
| @Override |
| public void stopNetLog() { |
| - nativeStopNetLog(mUrlRequestContextAdapter); |
| + synchronized (mLock) { |
| + if (mUrlRequestContextAdapter == 0) { |
| + throw new IllegalStateException( |
| + "Context is shutdown."); |
| + } |
| + nativeStopNetLog(mUrlRequestContextAdapter); |
| + } |
| } |
| /** |
| @@ -103,10 +157,12 @@ public class CronetUrlRequestContext extends UrlRequestContext { |
| } |
| long getUrlRequestContextAdapter() { |
| - if (mUrlRequestContextAdapter == 0) { |
| - throw new IllegalStateException("Context Adapter is destroyed."); |
| + synchronized (mLock) { |
| + if (mUrlRequestContextAdapter == 0) { |
| + throw new IllegalStateException("Context is shutdown."); |
| + } |
| + return mUrlRequestContextAdapter; |
| } |
| - return mUrlRequestContextAdapter; |
| } |
| /** |
| @@ -128,7 +184,9 @@ public class CronetUrlRequestContext extends UrlRequestContext { |
| @SuppressWarnings("unused") |
| @CalledByNative |
| private void initNetworkThread() { |
| - mNetworkThread = Thread.currentThread(); |
| + synchronized (mLock) { |
| + mNetworkThread = Thread.currentThread(); |
| + } |
| Thread.currentThread().setName("ChromiumNet"); |
| Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); |
| } |
| @@ -146,4 +204,7 @@ public class CronetUrlRequestContext extends UrlRequestContext { |
| private native void nativeStopNetLog(long urlRequestContextAdapter); |
| private native int nativeSetMinLogLevel(int loggingLevel); |
| + |
| + private native void nativeInitRequestContextOnMainThread( |
| + long urlRequestContextAdapter); |
| } |