| Index: components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java
|
| diff --git a/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java b/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java
|
| index d7da13995e5e93778193615b2acd737971a373fa..795a68d26296e8fc918d9f11347489eb4886a6b4 100644
|
| --- a/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java
|
| +++ b/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java
|
| @@ -13,6 +13,7 @@ import org.chromium.base.annotations.CalledByNative;
|
| import org.chromium.base.annotations.JNIAdditionalImport;
|
| import org.chromium.base.annotations.JNINamespace;
|
| import org.chromium.base.annotations.NativeClassQualifiedName;
|
| +import org.chromium.net.InlineExecutionProhibitedException;
|
| import org.chromium.net.Preconditions;
|
| import org.chromium.net.QuicException;
|
| import org.chromium.net.RequestFinishedInfo;
|
| @@ -49,6 +50,7 @@ import javax.annotation.concurrent.GuardedBy;
|
| public final class CronetUrlRequest implements UrlRequest {
|
| private static final RequestFinishedInfo.Metrics EMPTY_METRICS =
|
| new RequestFinishedInfo.Metrics(null, null, null, null);
|
| + private final boolean mAllowDirectExecutor;
|
|
|
| /* Native adapter object, owned by UrlRequest. */
|
| @GuardedBy("mUrlRequestAdapterLock")
|
| @@ -57,6 +59,8 @@ public final class CronetUrlRequest implements UrlRequest {
|
| @GuardedBy("mUrlRequestAdapterLock")
|
| private boolean mStarted = false;
|
| @GuardedBy("mUrlRequestAdapterLock")
|
| + private boolean mFailed = false;
|
| + @GuardedBy("mUrlRequestAdapterLock")
|
| private boolean mWaitingOnRedirect = false;
|
| @GuardedBy("mUrlRequestAdapterLock")
|
| private boolean mWaitingOnRead = false;
|
| @@ -109,6 +113,7 @@ public final class CronetUrlRequest implements UrlRequest {
|
|
|
| @Override
|
| public void run() {
|
| + checkCallingThread();
|
| // Null out mByteBuffer, to pass buffer ownership to callback or release if done.
|
| ByteBuffer buffer = mByteBuffer;
|
| mByteBuffer = null;
|
| @@ -130,7 +135,7 @@ public final class CronetUrlRequest implements UrlRequest {
|
| CronetUrlRequest(CronetUrlRequestContext requestContext, String url, int priority,
|
| UrlRequest.Callback callback, Executor executor, Collection<Object> requestAnnotations,
|
| boolean metricsCollectionEnabled, boolean disableCache,
|
| - boolean disableConnectionMigration) {
|
| + boolean disableConnectionMigration, boolean allowDirectExecutor) {
|
| if (url == null) {
|
| throw new NullPointerException("URL is required");
|
| }
|
| @@ -144,6 +149,7 @@ public final class CronetUrlRequest implements UrlRequest {
|
| throw new NullPointerException("requestAnnotations is required");
|
| }
|
|
|
| + mAllowDirectExecutor = allowDirectExecutor;
|
| mRequestContext = requestContext;
|
| mInitialUrl = url;
|
| mUrlChain.add(url);
|
| @@ -223,10 +229,9 @@ public final class CronetUrlRequest implements UrlRequest {
|
| "Requests with upload data must have a Content-Type.");
|
| }
|
| mStarted = true;
|
| - mUploadDataStream.postTaskToExecutor(new Runnable() {
|
| + mUploadDataStream.initializeWithRequest(CronetUrlRequest.this, new Runnable() {
|
| @Override
|
| public void run() {
|
| - mUploadDataStream.initializeWithRequest(CronetUrlRequest.this);
|
| synchronized (mUrlRequestAdapterLock) {
|
| if (isDoneLocked()) {
|
| return;
|
| @@ -369,6 +374,8 @@ public final class CronetUrlRequest implements UrlRequest {
|
| failException);
|
| // If posting a task throws an exception, then there is no choice
|
| // but to destroy the request without invoking the callback.
|
| + failWithException(
|
| + new UrlRequestException("Exception posting task to executor", failException));
|
| destroyRequestAdapter(false);
|
| }
|
| }
|
| @@ -466,6 +473,13 @@ public final class CronetUrlRequest implements UrlRequest {
|
| * Fails the request with an exception. Can be called on any thread.
|
| */
|
| private void failWithException(final UrlRequestException exception) {
|
| + synchronized (mUrlRequestAdapterLock) {
|
| + if (mFailed) {
|
| + return;
|
| + } else {
|
| + mFailed = true;
|
| + }
|
| + }
|
| Runnable task = new Runnable() {
|
| @Override
|
| public void run() {
|
| @@ -482,7 +496,11 @@ public final class CronetUrlRequest implements UrlRequest {
|
| }
|
| }
|
| };
|
| - postTaskToExecutor(task);
|
| + try {
|
| + mExecutor.execute(task);
|
| + } catch (RejectedExecutionException e) {
|
| + Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to executor", e);
|
| + }
|
| }
|
|
|
| ////////////////////////////////////////////////
|
| @@ -517,6 +535,7 @@ public final class CronetUrlRequest implements UrlRequest {
|
| Runnable task = new Runnable() {
|
| @Override
|
| public void run() {
|
| + checkCallingThread();
|
| synchronized (mUrlRequestAdapterLock) {
|
| if (isDoneLocked()) {
|
| return;
|
| @@ -547,6 +566,7 @@ public final class CronetUrlRequest implements UrlRequest {
|
| Runnable task = new Runnable() {
|
| @Override
|
| public void run() {
|
| + checkCallingThread();
|
| synchronized (mUrlRequestAdapterLock) {
|
| if (isDoneLocked()) {
|
| return;
|
| @@ -736,6 +756,13 @@ public final class CronetUrlRequest implements UrlRequest {
|
| }
|
| }
|
|
|
| + /** Enforces prohibition of direct execution. */
|
| + private void checkCallingThread() {
|
| + if (!mAllowDirectExecutor && mRequestContext.isNativeThread(Thread.currentThread())) {
|
| + throw new InlineExecutionProhibitedException();
|
| + }
|
| + }
|
| +
|
| // Native methods are implemented in cronet_url_request_adapter.cc.
|
|
|
| private native long nativeCreateRequestAdapter(long urlRequestContextAdapter, String url,
|
|
|