Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(412)

Side by Side Diff: components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java

Issue 2283243002: Allow direct executors in cronet. (Closed)
Patch Set: Refactor DirectPreventingExecutor, and fix closing logic Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.net.impl; 5 package org.chromium.net.impl;
6 6
7 import android.os.SystemClock; 7 import android.os.SystemClock;
8 import android.support.annotation.Nullable; 8 import android.support.annotation.Nullable;
9 import android.util.Log; 9 import android.util.Log;
10 10
11 import org.chromium.base.VisibleForTesting; 11 import org.chromium.base.VisibleForTesting;
12 import org.chromium.base.annotations.CalledByNative; 12 import org.chromium.base.annotations.CalledByNative;
13 import org.chromium.base.annotations.JNIAdditionalImport; 13 import org.chromium.base.annotations.JNIAdditionalImport;
14 import org.chromium.base.annotations.JNINamespace; 14 import org.chromium.base.annotations.JNINamespace;
15 import org.chromium.base.annotations.NativeClassQualifiedName; 15 import org.chromium.base.annotations.NativeClassQualifiedName;
16 import org.chromium.net.InlineExecutionProhibitedException;
16 import org.chromium.net.Preconditions; 17 import org.chromium.net.Preconditions;
17 import org.chromium.net.QuicException; 18 import org.chromium.net.QuicException;
18 import org.chromium.net.RequestFinishedInfo; 19 import org.chromium.net.RequestFinishedInfo;
19 import org.chromium.net.RequestPriority; 20 import org.chromium.net.RequestPriority;
20 import org.chromium.net.UploadDataProvider; 21 import org.chromium.net.UploadDataProvider;
21 import org.chromium.net.UrlRequest; 22 import org.chromium.net.UrlRequest;
22 import org.chromium.net.UrlRequestException; 23 import org.chromium.net.UrlRequestException;
23 import org.chromium.net.UrlResponseInfo; 24 import org.chromium.net.UrlResponseInfo;
24 25
25 import java.nio.ByteBuffer; 26 import java.nio.ByteBuffer;
(...skipping 16 matching lines...) Expand all
42 * native tasks to native network thread. Because Cancel could be called from 43 * native tasks to native network thread. Because Cancel could be called from
43 * any thread it is protected by mUrlRequestAdapterLock. 44 * any thread it is protected by mUrlRequestAdapterLock.
44 */ 45 */
45 @JNINamespace("cronet") 46 @JNINamespace("cronet")
46 // Qualifies UrlRequest.StatusListener which is used in onStatus, a JNI method. 47 // Qualifies UrlRequest.StatusListener which is used in onStatus, a JNI method.
47 @JNIAdditionalImport(UrlRequest.class) 48 @JNIAdditionalImport(UrlRequest.class)
48 @VisibleForTesting 49 @VisibleForTesting
49 public final class CronetUrlRequest implements UrlRequest { 50 public final class CronetUrlRequest implements UrlRequest {
50 private static final RequestFinishedInfo.Metrics EMPTY_METRICS = 51 private static final RequestFinishedInfo.Metrics EMPTY_METRICS =
51 new RequestFinishedInfo.Metrics(null, null, null, null); 52 new RequestFinishedInfo.Metrics(null, null, null, null);
53 private final boolean mAllowDirectExecutor;
52 54
53 /* Native adapter object, owned by UrlRequest. */ 55 /* Native adapter object, owned by UrlRequest. */
54 @GuardedBy("mUrlRequestAdapterLock") 56 @GuardedBy("mUrlRequestAdapterLock")
55 private long mUrlRequestAdapter; 57 private long mUrlRequestAdapter;
56 58
57 @GuardedBy("mUrlRequestAdapterLock") 59 @GuardedBy("mUrlRequestAdapterLock")
58 private boolean mStarted = false; 60 private boolean mStarted = false;
59 @GuardedBy("mUrlRequestAdapterLock") 61 @GuardedBy("mUrlRequestAdapterLock")
60 private boolean mWaitingOnRedirect = false; 62 private boolean mWaitingOnRedirect = false;
61 @GuardedBy("mUrlRequestAdapterLock") 63 @GuardedBy("mUrlRequestAdapterLock")
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 private Runnable mOnDestroyedCallbackForTesting; 104 private Runnable mOnDestroyedCallbackForTesting;
103 105
104 private static final class HeadersList extends ArrayList<Map.Entry<String, S tring>> {} 106 private static final class HeadersList extends ArrayList<Map.Entry<String, S tring>> {}
105 107
106 private final class OnReadCompletedRunnable implements Runnable { 108 private final class OnReadCompletedRunnable implements Runnable {
107 // Buffer passed back from current invocation of onReadCompleted. 109 // Buffer passed back from current invocation of onReadCompleted.
108 ByteBuffer mByteBuffer; 110 ByteBuffer mByteBuffer;
109 111
110 @Override 112 @Override
111 public void run() { 113 public void run() {
114 checkCallingThread();
112 // Null out mByteBuffer, to pass buffer ownership to callback or rel ease if done. 115 // Null out mByteBuffer, to pass buffer ownership to callback or rel ease if done.
113 ByteBuffer buffer = mByteBuffer; 116 ByteBuffer buffer = mByteBuffer;
114 mByteBuffer = null; 117 mByteBuffer = null;
115 118
116 try { 119 try {
117 synchronized (mUrlRequestAdapterLock) { 120 synchronized (mUrlRequestAdapterLock) {
118 if (isDoneLocked()) { 121 if (isDoneLocked()) {
119 return; 122 return;
120 } 123 }
121 mWaitingOnRead = true; 124 mWaitingOnRead = true;
122 } 125 }
123 mCallback.onReadCompleted(CronetUrlRequest.this, mResponseInfo, buffer); 126 mCallback.onReadCompleted(CronetUrlRequest.this, mResponseInfo, buffer);
124 } catch (Exception e) { 127 } catch (Exception e) {
125 onCallbackException(e); 128 onCallbackException(e);
126 } 129 }
127 } 130 }
128 } 131 }
129 132
130 CronetUrlRequest(CronetUrlRequestContext requestContext, String url, int pri ority, 133 CronetUrlRequest(CronetUrlRequestContext requestContext, String url, int pri ority,
131 UrlRequest.Callback callback, Executor executor, Collection<Object> requestAnnotations, 134 UrlRequest.Callback callback, Executor executor, Collection<Object> requestAnnotations,
132 boolean metricsCollectionEnabled, boolean disableCache, 135 boolean metricsCollectionEnabled, boolean disableCache,
133 boolean disableConnectionMigration) { 136 boolean disableConnectionMigration, boolean allowDirectExecutor) {
134 if (url == null) { 137 if (url == null) {
135 throw new NullPointerException("URL is required"); 138 throw new NullPointerException("URL is required");
136 } 139 }
137 if (callback == null) { 140 if (callback == null) {
138 throw new NullPointerException("Listener is required"); 141 throw new NullPointerException("Listener is required");
139 } 142 }
140 if (executor == null) { 143 if (executor == null) {
141 throw new NullPointerException("Executor is required"); 144 throw new NullPointerException("Executor is required");
142 } 145 }
143 if (requestAnnotations == null) { 146 if (requestAnnotations == null) {
144 throw new NullPointerException("requestAnnotations is required"); 147 throw new NullPointerException("requestAnnotations is required");
145 } 148 }
146 149
150 mAllowDirectExecutor = allowDirectExecutor;
147 mRequestContext = requestContext; 151 mRequestContext = requestContext;
148 mInitialUrl = url; 152 mInitialUrl = url;
149 mUrlChain.add(url); 153 mUrlChain.add(url);
150 mPriority = convertRequestPriority(priority); 154 mPriority = convertRequestPriority(priority);
151 mCallback = callback; 155 mCallback = callback;
152 mExecutor = executor; 156 mExecutor = executor;
153 mRequestAnnotations = requestAnnotations; 157 mRequestAnnotations = requestAnnotations;
154 mRequestMetricsAccumulator = 158 mRequestMetricsAccumulator =
155 metricsCollectionEnabled ? new UrlRequestMetricsAccumulator() : null; 159 metricsCollectionEnabled ? new UrlRequestMetricsAccumulator() : null;
156 mDisableCache = disableCache; 160 mDisableCache = disableCache;
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 /** 364 /**
361 * Posts task to application Executor. Used for Listener callbacks 365 * Posts task to application Executor. Used for Listener callbacks
362 * and other tasks that should not be executed on network thread. 366 * and other tasks that should not be executed on network thread.
363 */ 367 */
364 private void postTaskToExecutor(Runnable task) { 368 private void postTaskToExecutor(Runnable task) {
365 try { 369 try {
366 mExecutor.execute(task); 370 mExecutor.execute(task);
367 } catch (RejectedExecutionException failException) { 371 } catch (RejectedExecutionException failException) {
368 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex ecutor", 372 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex ecutor",
369 failException); 373 failException);
370 // If posting a task throws an exception, then there is no choice 374 // If posting a task throws an exception, then we fail the request. This exception could
371 // but to destroy the request without invoking the callback. 375 // be permanent (executor shutdown), transient (AbortPolicy, or Call erRunsPolicy with
372 destroyRequestAdapter(false); 376 // direct execution not permitted), or caused by the runnables we su bmit if
377 // mUserExecutor is a direct executor and direct execution is not pe rmitted. In the
378 // latter two cases, there is at least have a chance to inform the e mbedder of the
379 // request's failure, since failWithException does not enforce that onFailed() is not
380 // executed inline.
381 failWithException(
382 new UrlRequestException("Exception posting task to executor" , failException));
373 } 383 }
374 } 384 }
375 385
376 private static int convertRequestPriority(int priority) { 386 private static int convertRequestPriority(int priority) {
377 switch (priority) { 387 switch (priority) {
378 case Builder.REQUEST_PRIORITY_IDLE: 388 case Builder.REQUEST_PRIORITY_IDLE:
379 return RequestPriority.IDLE; 389 return RequestPriority.IDLE;
380 case Builder.REQUEST_PRIORITY_LOWEST: 390 case Builder.REQUEST_PRIORITY_LOWEST:
381 return RequestPriority.LOWEST; 391 return RequestPriority.LOWEST;
382 case Builder.REQUEST_PRIORITY_LOW: 392 case Builder.REQUEST_PRIORITY_LOW:
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 440
431 /** 441 /**
432 * If callback method throws an exception, request gets canceled 442 * If callback method throws an exception, request gets canceled
433 * and exception is reported via onFailed listener callback. 443 * and exception is reported via onFailed listener callback.
434 * Only called on the Executor. 444 * Only called on the Executor.
435 */ 445 */
436 private void onCallbackException(Exception e) { 446 private void onCallbackException(Exception e) {
437 UrlRequestException requestError = 447 UrlRequestException requestError =
438 new UrlRequestException("Exception received from UrlRequest.Call back", e); 448 new UrlRequestException("Exception received from UrlRequest.Call back", e);
439 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in CalledByNative meth od", e); 449 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in CalledByNative meth od", e);
440 // Do not call into listener if request is finished. 450 failWithException(requestError);
441 synchronized (mUrlRequestAdapterLock) {
442 if (isDoneLocked()) {
443 return;
444 }
445 destroyRequestAdapter(false);
446 }
447 try {
448 mCallback.onFailed(this, mResponseInfo, requestError);
449 } catch (Exception failException) {
450 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception notifying of faile d request",
451 failException);
452 }
453 } 451 }
454 452
455 /** 453 /**
456 * Called when UploadDataProvider encounters an error. 454 * Called when UploadDataProvider encounters an error.
457 */ 455 */
458 void onUploadException(Throwable e) { 456 void onUploadException(Throwable e) {
459 UrlRequestException uploadError = 457 UrlRequestException uploadError =
460 new UrlRequestException("Exception received from UploadDataProvi der", e); 458 new UrlRequestException("Exception received from UploadDataProvi der", e);
461 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in upload method", e); 459 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in upload method", e);
462 failWithException(uploadError); 460 failWithException(uploadError);
463 } 461 }
464 462
465 /** 463 /**
466 * Fails the request with an exception. Can be called on any thread. 464 * Fails the request with an exception. Can be called on any thread.
467 */ 465 */
468 private void failWithException(final UrlRequestException exception) { 466 private void failWithException(final UrlRequestException exception) {
467 synchronized (mUrlRequestAdapterLock) {
468 if (isDoneLocked()) {
469 return;
470 }
471 destroyRequestAdapter(false);
472 }
469 Runnable task = new Runnable() { 473 Runnable task = new Runnable() {
470 @Override 474 @Override
471 public void run() { 475 public void run() {
472 synchronized (mUrlRequestAdapterLock) {
473 if (isDoneLocked()) {
474 return;
475 }
476 destroyRequestAdapter(false);
477 }
478 try { 476 try {
479 mCallback.onFailed(CronetUrlRequest.this, mResponseInfo, exc eption); 477 mCallback.onFailed(CronetUrlRequest.this, mResponseInfo, exc eption);
480 } catch (Exception e) { 478 } catch (Exception e) {
481 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onError method", e); 479 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onFaile d method", e);
482 } 480 }
483 } 481 }
484 }; 482 };
485 postTaskToExecutor(task); 483 try {
484 mExecutor.execute(task);
485 } catch (RejectedExecutionException e) {
486 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex ecutor", e);
487 }
486 } 488 }
487 489
488 //////////////////////////////////////////////// 490 ////////////////////////////////////////////////
489 // Private methods called by the native code. 491 // Private methods called by the native code.
490 // Always called on network thread. 492 // Always called on network thread.
491 //////////////////////////////////////////////// 493 ////////////////////////////////////////////////
492 494
493 /** 495 /**
494 * Called before following redirects. The redirect will only be followed if 496 * Called before following redirects. The redirect will only be followed if
495 * {@link #followRedirect()} is called. If the redirect response has a body, it will be ignored. 497 * {@link #followRedirect()} is called. If the redirect response has a body, it will be ignored.
(...skipping 14 matching lines...) Expand all
510 httpStatusText, headers, wasCached, negotiatedProtocol, proxySer ver); 512 httpStatusText, headers, wasCached, negotiatedProtocol, proxySer ver);
511 mReceivedBytesCountFromRedirects += receivedBytesCount; 513 mReceivedBytesCountFromRedirects += receivedBytesCount;
512 responseInfo.setReceivedBytesCount(mReceivedBytesCountFromRedirects); 514 responseInfo.setReceivedBytesCount(mReceivedBytesCountFromRedirects);
513 515
514 // Have to do this after creating responseInfo. 516 // Have to do this after creating responseInfo.
515 mUrlChain.add(newLocation); 517 mUrlChain.add(newLocation);
516 518
517 Runnable task = new Runnable() { 519 Runnable task = new Runnable() {
518 @Override 520 @Override
519 public void run() { 521 public void run() {
522 checkCallingThread();
520 synchronized (mUrlRequestAdapterLock) { 523 synchronized (mUrlRequestAdapterLock) {
521 if (isDoneLocked()) { 524 if (isDoneLocked()) {
522 return; 525 return;
523 } 526 }
524 mWaitingOnRedirect = true; 527 mWaitingOnRedirect = true;
525 } 528 }
526 529
527 try { 530 try {
528 mCallback.onRedirectReceived(CronetUrlRequest.this, response Info, newLocation); 531 mCallback.onRedirectReceived(CronetUrlRequest.this, response Info, newLocation);
529 } catch (Exception e) { 532 } catch (Exception e) {
(...skipping 10 matching lines...) Expand all
540 */ 543 */
541 @SuppressWarnings("unused") 544 @SuppressWarnings("unused")
542 @CalledByNative 545 @CalledByNative
543 private void onResponseStarted(int httpStatusCode, String httpStatusText, St ring[] headers, 546 private void onResponseStarted(int httpStatusCode, String httpStatusText, St ring[] headers,
544 boolean wasCached, String negotiatedProtocol, String proxyServer) { 547 boolean wasCached, String negotiatedProtocol, String proxyServer) {
545 mResponseInfo = prepareResponseInfoOnNetworkThread(httpStatusCode, httpS tatusText, headers, 548 mResponseInfo = prepareResponseInfoOnNetworkThread(httpStatusCode, httpS tatusText, headers,
546 wasCached, negotiatedProtocol, proxyServer); 549 wasCached, negotiatedProtocol, proxyServer);
547 Runnable task = new Runnable() { 550 Runnable task = new Runnable() {
548 @Override 551 @Override
549 public void run() { 552 public void run() {
553 checkCallingThread();
550 synchronized (mUrlRequestAdapterLock) { 554 synchronized (mUrlRequestAdapterLock) {
551 if (isDoneLocked()) { 555 if (isDoneLocked()) {
552 return; 556 return;
553 } 557 }
554 if (mRequestMetricsAccumulator != null) { 558 if (mRequestMetricsAccumulator != null) {
555 mRequestMetricsAccumulator.onResponseStarted(); 559 mRequestMetricsAccumulator.onResponseStarted();
556 } 560 }
557 mWaitingOnRead = true; 561 mWaitingOnRead = true;
558 } 562 }
559 563
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 } 733 }
730 } 734 }
731 735
732 private void onResponseStarted() { 736 private void onResponseStarted() {
733 if (mRequestStartTime != null && mTtfbMs == null) { 737 if (mRequestStartTime != null && mTtfbMs == null) {
734 mTtfbMs = SystemClock.elapsedRealtime() - mRequestStartTime; 738 mTtfbMs = SystemClock.elapsedRealtime() - mRequestStartTime;
735 } 739 }
736 } 740 }
737 } 741 }
738 742
743 /** Enforces prohibition of direct execution. */
744 void checkCallingThread() {
745 if (!mAllowDirectExecutor && mRequestContext.isNetworkThread(Thread.curr entThread())) {
746 throw new InlineExecutionProhibitedException();
747 }
748 }
749
739 // Native methods are implemented in cronet_url_request_adapter.cc. 750 // Native methods are implemented in cronet_url_request_adapter.cc.
740 751
741 private native long nativeCreateRequestAdapter(long urlRequestContextAdapter , String url, 752 private native long nativeCreateRequestAdapter(long urlRequestContextAdapter , String url,
742 int priority, boolean disableCache, boolean disableConnectionMigrati on); 753 int priority, boolean disableCache, boolean disableConnectionMigrati on);
743 754
744 @NativeClassQualifiedName("CronetURLRequestAdapter") 755 @NativeClassQualifiedName("CronetURLRequestAdapter")
745 private native boolean nativeSetHttpMethod(long nativePtr, String method); 756 private native boolean nativeSetHttpMethod(long nativePtr, String method);
746 757
747 @NativeClassQualifiedName("CronetURLRequestAdapter") 758 @NativeClassQualifiedName("CronetURLRequestAdapter")
748 private native boolean nativeAddRequestHeader(long nativePtr, String name, S tring value); 759 private native boolean nativeAddRequestHeader(long nativePtr, String name, S tring value);
749 760
750 @NativeClassQualifiedName("CronetURLRequestAdapter") 761 @NativeClassQualifiedName("CronetURLRequestAdapter")
751 private native void nativeStart(long nativePtr); 762 private native void nativeStart(long nativePtr);
752 763
753 @NativeClassQualifiedName("CronetURLRequestAdapter") 764 @NativeClassQualifiedName("CronetURLRequestAdapter")
754 private native void nativeFollowDeferredRedirect(long nativePtr); 765 private native void nativeFollowDeferredRedirect(long nativePtr);
755 766
756 @NativeClassQualifiedName("CronetURLRequestAdapter") 767 @NativeClassQualifiedName("CronetURLRequestAdapter")
757 private native boolean nativeReadData( 768 private native boolean nativeReadData(
758 long nativePtr, ByteBuffer byteBuffer, int position, int capacity); 769 long nativePtr, ByteBuffer byteBuffer, int position, int capacity);
759 770
760 @NativeClassQualifiedName("CronetURLRequestAdapter") 771 @NativeClassQualifiedName("CronetURLRequestAdapter")
761 private native void nativeDestroy(long nativePtr, boolean sendOnCanceled); 772 private native void nativeDestroy(long nativePtr, boolean sendOnCanceled);
762 773
763 @NativeClassQualifiedName("CronetURLRequestAdapter") 774 @NativeClassQualifiedName("CronetURLRequestAdapter")
764 private native void nativeGetStatus(long nativePtr, UrlRequest.StatusListene r listener); 775 private native void nativeGetStatus(long nativePtr, UrlRequest.StatusListene r listener);
765 } 776 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698