| 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..40c91d2241ada52b7408e0f5eef9273b58c55110 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 final ConditionVariable mInitCompleted = new ConditionVariable(false);
|
| + private final AtomicInteger mActiveRequestCount = new AtomicInteger(0);
|
| +
|
| private long mUrlRequestContextAdapter = 0;
|
| private Thread mNetworkThread;
|
| - 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");
|
| + throw new NullPointerException("Context Adapter creation failed.");
|
| + }
|
| +
|
| + // Init native Chromium URLRequestContext on main UI thread.
|
| + Runnable task = new Runnable() {
|
| + @Override
|
| + 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);
|
| + }
|
| + }
|
| + };
|
| + // Run task immediately or post it to the UI thread.
|
| + if (Looper.getMainLooper() == Looper.myLooper()) {
|
| + task.run();
|
| + } else {
|
| + 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) {
|
| + checkHaveAdapter();
|
| + 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,47 @@ public class CronetUrlRequestContext extends UrlRequestContext {
|
|
|
| @Override
|
| public void shutdown() {
|
| - if (mActiveRequestCount.get() != 0) {
|
| - throw new IllegalStateException(
|
| - "Cannot shutdown with active requests.");
|
| + synchronized (mLock) {
|
| + checkHaveAdapter();
|
| + 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 and network thread (without lock,
|
| + // so other thread could access it).
|
| + mInitCompleted.block();
|
| +
|
| + synchronized (mLock) {
|
| + // It is possible that adapter is already destroyed on another thread.
|
| + if (!haveRequestContextAdapter()) {
|
| + return;
|
| + }
|
| + nativeDestroyRequestContextAdapter(mUrlRequestContextAdapter);
|
| + mUrlRequestContextAdapter = 0;
|
| }
|
| - nativeDestroyRequestContextAdapter(mUrlRequestContextAdapter);
|
| - mUrlRequestContextAdapter = 0;
|
| }
|
|
|
| @Override
|
| public void startNetLogToFile(String fileName) {
|
| - nativeStartNetLogToFile(mUrlRequestContextAdapter, fileName);
|
| + synchronized (mLock) {
|
| + checkHaveAdapter();
|
| + nativeStartNetLogToFile(mUrlRequestContextAdapter, fileName);
|
| + }
|
| }
|
|
|
| @Override
|
| public void stopNetLog() {
|
| - nativeStopNetLog(mUrlRequestContextAdapter);
|
| + synchronized (mLock) {
|
| + checkHaveAdapter();
|
| + nativeStopNetLog(mUrlRequestContextAdapter);
|
| + }
|
| }
|
|
|
| /**
|
| @@ -103,10 +150,20 @@ public class CronetUrlRequestContext extends UrlRequestContext {
|
| }
|
|
|
| long getUrlRequestContextAdapter() {
|
| - if (mUrlRequestContextAdapter == 0) {
|
| - throw new IllegalStateException("Context Adapter is destroyed.");
|
| + synchronized (mLock) {
|
| + checkHaveAdapter();
|
| + return mUrlRequestContextAdapter;
|
| }
|
| - return mUrlRequestContextAdapter;
|
| + }
|
| +
|
| + private void checkHaveAdapter() throws IllegalStateException {
|
| + if (!haveRequestContextAdapter()) {
|
| + throw new IllegalStateException("Context is shut down.");
|
| + }
|
| + }
|
| +
|
| + private boolean haveRequestContextAdapter() {
|
| + return mUrlRequestContextAdapter != 0;
|
| }
|
|
|
| /**
|
| @@ -128,7 +185,10 @@ public class CronetUrlRequestContext extends UrlRequestContext {
|
| @SuppressWarnings("unused")
|
| @CalledByNative
|
| private void initNetworkThread() {
|
| - mNetworkThread = Thread.currentThread();
|
| + synchronized (mLock) {
|
| + mNetworkThread = Thread.currentThread();
|
| + mInitCompleted.open();
|
| + }
|
| Thread.currentThread().setName("ChromiumNet");
|
| Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
|
| }
|
| @@ -146,4 +206,7 @@ public class CronetUrlRequestContext extends UrlRequestContext {
|
| private native void nativeStopNetLog(long urlRequestContextAdapter);
|
|
|
| private native int nativeSetMinLogLevel(int loggingLevel);
|
| +
|
| + private native void nativeInitRequestContextOnMainThread(
|
| + long urlRequestContextAdapter);
|
| }
|
|
|