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

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: Addressed comments 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")
62 private boolean mFailed = false;
63 @GuardedBy("mUrlRequestAdapterLock")
60 private boolean mWaitingOnRedirect = false; 64 private boolean mWaitingOnRedirect = false;
61 @GuardedBy("mUrlRequestAdapterLock") 65 @GuardedBy("mUrlRequestAdapterLock")
62 private boolean mWaitingOnRead = false; 66 private boolean mWaitingOnRead = false;
63 @GuardedBy("mUrlRequestAdapterLock") 67 @GuardedBy("mUrlRequestAdapterLock")
64 @Nullable 68 @Nullable
65 private final UrlRequestMetricsAccumulator mRequestMetricsAccumulator; 69 private final UrlRequestMetricsAccumulator mRequestMetricsAccumulator;
66 70
67 /* 71 /*
68 * Synchronize access to mUrlRequestAdapter, mStarted, mWaitingOnRedirect, 72 * Synchronize access to mUrlRequestAdapter, mStarted, mWaitingOnRedirect,
69 * and mWaitingOnRead. 73 * and mWaitingOnRead.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 private Runnable mOnDestroyedCallbackForTesting; 106 private Runnable mOnDestroyedCallbackForTesting;
103 107
104 private static final class HeadersList extends ArrayList<Map.Entry<String, S tring>> {} 108 private static final class HeadersList extends ArrayList<Map.Entry<String, S tring>> {}
105 109
106 private final class OnReadCompletedRunnable implements Runnable { 110 private final class OnReadCompletedRunnable implements Runnable {
107 // Buffer passed back from current invocation of onReadCompleted. 111 // Buffer passed back from current invocation of onReadCompleted.
108 ByteBuffer mByteBuffer; 112 ByteBuffer mByteBuffer;
109 113
110 @Override 114 @Override
111 public void run() { 115 public void run() {
116 checkCallingThread();
112 // Null out mByteBuffer, to pass buffer ownership to callback or rel ease if done. 117 // Null out mByteBuffer, to pass buffer ownership to callback or rel ease if done.
113 ByteBuffer buffer = mByteBuffer; 118 ByteBuffer buffer = mByteBuffer;
114 mByteBuffer = null; 119 mByteBuffer = null;
115 120
116 try { 121 try {
117 synchronized (mUrlRequestAdapterLock) { 122 synchronized (mUrlRequestAdapterLock) {
118 if (isDoneLocked()) { 123 if (isDoneLocked()) {
119 return; 124 return;
120 } 125 }
121 mWaitingOnRead = true; 126 mWaitingOnRead = true;
122 } 127 }
123 mCallback.onReadCompleted(CronetUrlRequest.this, mResponseInfo, buffer); 128 mCallback.onReadCompleted(CronetUrlRequest.this, mResponseInfo, buffer);
124 } catch (Exception e) { 129 } catch (Exception e) {
125 onCallbackException(e); 130 onCallbackException(e);
126 } 131 }
127 } 132 }
128 } 133 }
129 134
130 CronetUrlRequest(CronetUrlRequestContext requestContext, String url, int pri ority, 135 CronetUrlRequest(CronetUrlRequestContext requestContext, String url, int pri ority,
131 UrlRequest.Callback callback, Executor executor, Collection<Object> requestAnnotations, 136 UrlRequest.Callback callback, Executor executor, Collection<Object> requestAnnotations,
132 boolean metricsCollectionEnabled, boolean disableCache, 137 boolean metricsCollectionEnabled, boolean disableCache,
133 boolean disableConnectionMigration) { 138 boolean disableConnectionMigration, boolean allowDirectExecutor) {
134 if (url == null) { 139 if (url == null) {
135 throw new NullPointerException("URL is required"); 140 throw new NullPointerException("URL is required");
136 } 141 }
137 if (callback == null) { 142 if (callback == null) {
138 throw new NullPointerException("Listener is required"); 143 throw new NullPointerException("Listener is required");
139 } 144 }
140 if (executor == null) { 145 if (executor == null) {
141 throw new NullPointerException("Executor is required"); 146 throw new NullPointerException("Executor is required");
142 } 147 }
143 if (requestAnnotations == null) { 148 if (requestAnnotations == null) {
144 throw new NullPointerException("requestAnnotations is required"); 149 throw new NullPointerException("requestAnnotations is required");
145 } 150 }
146 151
152 mAllowDirectExecutor = allowDirectExecutor;
147 mRequestContext = requestContext; 153 mRequestContext = requestContext;
148 mInitialUrl = url; 154 mInitialUrl = url;
149 mUrlChain.add(url); 155 mUrlChain.add(url);
150 mPriority = convertRequestPriority(priority); 156 mPriority = convertRequestPriority(priority);
151 mCallback = callback; 157 mCallback = callback;
152 mExecutor = executor; 158 mExecutor = executor;
153 mRequestAnnotations = requestAnnotations; 159 mRequestAnnotations = requestAnnotations;
154 mRequestMetricsAccumulator = 160 mRequestMetricsAccumulator =
155 metricsCollectionEnabled ? new UrlRequestMetricsAccumulator() : null; 161 metricsCollectionEnabled ? new UrlRequestMetricsAccumulator() : null;
156 mDisableCache = disableCache; 162 mDisableCache = disableCache;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 throw new IllegalArgumentException( 222 throw new IllegalArgumentException(
217 "Invalid header " + header.getKey() + "=" + head er.getValue()); 223 "Invalid header " + header.getKey() + "=" + head er.getValue());
218 } 224 }
219 } 225 }
220 if (mUploadDataStream != null) { 226 if (mUploadDataStream != null) {
221 if (!hasContentType) { 227 if (!hasContentType) {
222 throw new IllegalArgumentException( 228 throw new IllegalArgumentException(
223 "Requests with upload data must have a Content-T ype."); 229 "Requests with upload data must have a Content-T ype.");
224 } 230 }
225 mStarted = true; 231 mStarted = true;
226 mUploadDataStream.postTaskToExecutor(new Runnable() { 232 mUploadDataStream.initializeWithRequest(CronetUrlRequest.thi s, new Runnable() {
227 @Override 233 @Override
228 public void run() { 234 public void run() {
229 mUploadDataStream.initializeWithRequest(CronetUrlReq uest.this);
230 synchronized (mUrlRequestAdapterLock) { 235 synchronized (mUrlRequestAdapterLock) {
231 if (isDoneLocked()) { 236 if (isDoneLocked()) {
232 return; 237 return;
233 } 238 }
234 mUploadDataStream.attachNativeAdapterToRequest(m UrlRequestAdapter); 239 mUploadDataStream.attachNativeAdapterToRequest(m UrlRequestAdapter);
235 startInternalLocked(); 240 startInternalLocked();
236 } 241 }
237 } 242 }
238 }); 243 });
239 return; 244 return;
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 * and other tasks that should not be executed on network thread. 367 * and other tasks that should not be executed on network thread.
363 */ 368 */
364 private void postTaskToExecutor(Runnable task) { 369 private void postTaskToExecutor(Runnable task) {
365 try { 370 try {
366 mExecutor.execute(task); 371 mExecutor.execute(task);
367 } catch (RejectedExecutionException failException) { 372 } catch (RejectedExecutionException failException) {
368 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex ecutor", 373 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex ecutor",
369 failException); 374 failException);
370 // If posting a task throws an exception, then there is no choice 375 // If posting a task throws an exception, then there is no choice
371 // but to destroy the request without invoking the callback. 376 // but to destroy the request without invoking the callback.
377 failWithException(
378 new UrlRequestException("Exception posting task to executor" , failException));
372 destroyRequestAdapter(false); 379 destroyRequestAdapter(false);
373 } 380 }
374 } 381 }
375 382
376 private static int convertRequestPriority(int priority) { 383 private static int convertRequestPriority(int priority) {
377 switch (priority) { 384 switch (priority) {
378 case Builder.REQUEST_PRIORITY_IDLE: 385 case Builder.REQUEST_PRIORITY_IDLE:
379 return RequestPriority.IDLE; 386 return RequestPriority.IDLE;
380 case Builder.REQUEST_PRIORITY_LOWEST: 387 case Builder.REQUEST_PRIORITY_LOWEST:
381 return RequestPriority.LOWEST; 388 return RequestPriority.LOWEST;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 UrlRequestException uploadError = 466 UrlRequestException uploadError =
460 new UrlRequestException("Exception received from UploadDataProvi der", e); 467 new UrlRequestException("Exception received from UploadDataProvi der", e);
461 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in upload method", e); 468 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in upload method", e);
462 failWithException(uploadError); 469 failWithException(uploadError);
463 } 470 }
464 471
465 /** 472 /**
466 * Fails the request with an exception. Can be called on any thread. 473 * Fails the request with an exception. Can be called on any thread.
467 */ 474 */
468 private void failWithException(final UrlRequestException exception) { 475 private void failWithException(final UrlRequestException exception) {
476 synchronized (mUrlRequestAdapterLock) {
477 if (mFailed) {
478 return;
479 } else {
480 mFailed = true;
481 }
482 }
469 Runnable task = new Runnable() { 483 Runnable task = new Runnable() {
470 @Override 484 @Override
471 public void run() { 485 public void run() {
472 synchronized (mUrlRequestAdapterLock) { 486 synchronized (mUrlRequestAdapterLock) {
473 if (isDoneLocked()) { 487 if (isDoneLocked()) {
474 return; 488 return;
475 } 489 }
476 destroyRequestAdapter(false); 490 destroyRequestAdapter(false);
477 } 491 }
478 try { 492 try {
479 mCallback.onFailed(CronetUrlRequest.this, mResponseInfo, exc eption); 493 mCallback.onFailed(CronetUrlRequest.this, mResponseInfo, exc eption);
480 } catch (Exception e) { 494 } catch (Exception e) {
481 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onError method", e); 495 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onError method", e);
482 } 496 }
483 } 497 }
484 }; 498 };
485 postTaskToExecutor(task); 499 try {
500 mExecutor.execute(task);
501 } catch (RejectedExecutionException e) {
502 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex ecutor", e);
503 }
486 } 504 }
487 505
488 //////////////////////////////////////////////// 506 ////////////////////////////////////////////////
489 // Private methods called by the native code. 507 // Private methods called by the native code.
490 // Always called on network thread. 508 // Always called on network thread.
491 //////////////////////////////////////////////// 509 ////////////////////////////////////////////////
492 510
493 /** 511 /**
494 * Called before following redirects. The redirect will only be followed if 512 * 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. 513 * {@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); 528 httpStatusText, headers, wasCached, negotiatedProtocol, proxySer ver);
511 mReceivedBytesCountFromRedirects += receivedBytesCount; 529 mReceivedBytesCountFromRedirects += receivedBytesCount;
512 responseInfo.setReceivedBytesCount(mReceivedBytesCountFromRedirects); 530 responseInfo.setReceivedBytesCount(mReceivedBytesCountFromRedirects);
513 531
514 // Have to do this after creating responseInfo. 532 // Have to do this after creating responseInfo.
515 mUrlChain.add(newLocation); 533 mUrlChain.add(newLocation);
516 534
517 Runnable task = new Runnable() { 535 Runnable task = new Runnable() {
518 @Override 536 @Override
519 public void run() { 537 public void run() {
538 checkCallingThread();
520 synchronized (mUrlRequestAdapterLock) { 539 synchronized (mUrlRequestAdapterLock) {
521 if (isDoneLocked()) { 540 if (isDoneLocked()) {
522 return; 541 return;
523 } 542 }
524 mWaitingOnRedirect = true; 543 mWaitingOnRedirect = true;
525 } 544 }
526 545
527 try { 546 try {
528 mCallback.onRedirectReceived(CronetUrlRequest.this, response Info, newLocation); 547 mCallback.onRedirectReceived(CronetUrlRequest.this, response Info, newLocation);
529 } catch (Exception e) { 548 } catch (Exception e) {
(...skipping 10 matching lines...) Expand all
540 */ 559 */
541 @SuppressWarnings("unused") 560 @SuppressWarnings("unused")
542 @CalledByNative 561 @CalledByNative
543 private void onResponseStarted(int httpStatusCode, String httpStatusText, St ring[] headers, 562 private void onResponseStarted(int httpStatusCode, String httpStatusText, St ring[] headers,
544 boolean wasCached, String negotiatedProtocol, String proxyServer) { 563 boolean wasCached, String negotiatedProtocol, String proxyServer) {
545 mResponseInfo = prepareResponseInfoOnNetworkThread(httpStatusCode, httpS tatusText, headers, 564 mResponseInfo = prepareResponseInfoOnNetworkThread(httpStatusCode, httpS tatusText, headers,
546 wasCached, negotiatedProtocol, proxyServer); 565 wasCached, negotiatedProtocol, proxyServer);
547 Runnable task = new Runnable() { 566 Runnable task = new Runnable() {
548 @Override 567 @Override
549 public void run() { 568 public void run() {
569 checkCallingThread();
550 synchronized (mUrlRequestAdapterLock) { 570 synchronized (mUrlRequestAdapterLock) {
551 if (isDoneLocked()) { 571 if (isDoneLocked()) {
552 return; 572 return;
553 } 573 }
554 if (mRequestMetricsAccumulator != null) { 574 if (mRequestMetricsAccumulator != null) {
555 mRequestMetricsAccumulator.onResponseStarted(); 575 mRequestMetricsAccumulator.onResponseStarted();
556 } 576 }
557 mWaitingOnRead = true; 577 mWaitingOnRead = true;
558 } 578 }
559 579
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 } 749 }
730 } 750 }
731 751
732 private void onResponseStarted() { 752 private void onResponseStarted() {
733 if (mRequestStartTime != null && mTtfbMs == null) { 753 if (mRequestStartTime != null && mTtfbMs == null) {
734 mTtfbMs = SystemClock.elapsedRealtime() - mRequestStartTime; 754 mTtfbMs = SystemClock.elapsedRealtime() - mRequestStartTime;
735 } 755 }
736 } 756 }
737 } 757 }
738 758
759 /** Enforces prohibition of direct execution. */
760 private void checkCallingThread() {
761 if (!mAllowDirectExecutor && mRequestContext.isNativeThread(Thread.curre ntThread())) {
762 throw new InlineExecutionProhibitedException();
763 }
764 }
765
739 // Native methods are implemented in cronet_url_request_adapter.cc. 766 // Native methods are implemented in cronet_url_request_adapter.cc.
740 767
741 private native long nativeCreateRequestAdapter(long urlRequestContextAdapter , String url, 768 private native long nativeCreateRequestAdapter(long urlRequestContextAdapter , String url,
742 int priority, boolean disableCache, boolean disableConnectionMigrati on); 769 int priority, boolean disableCache, boolean disableConnectionMigrati on);
743 770
744 @NativeClassQualifiedName("CronetURLRequestAdapter") 771 @NativeClassQualifiedName("CronetURLRequestAdapter")
745 private native boolean nativeSetHttpMethod(long nativePtr, String method); 772 private native boolean nativeSetHttpMethod(long nativePtr, String method);
746 773
747 @NativeClassQualifiedName("CronetURLRequestAdapter") 774 @NativeClassQualifiedName("CronetURLRequestAdapter")
748 private native boolean nativeAddRequestHeader(long nativePtr, String name, S tring value); 775 private native boolean nativeAddRequestHeader(long nativePtr, String name, S tring value);
749 776
750 @NativeClassQualifiedName("CronetURLRequestAdapter") 777 @NativeClassQualifiedName("CronetURLRequestAdapter")
751 private native void nativeStart(long nativePtr); 778 private native void nativeStart(long nativePtr);
752 779
753 @NativeClassQualifiedName("CronetURLRequestAdapter") 780 @NativeClassQualifiedName("CronetURLRequestAdapter")
754 private native void nativeFollowDeferredRedirect(long nativePtr); 781 private native void nativeFollowDeferredRedirect(long nativePtr);
755 782
756 @NativeClassQualifiedName("CronetURLRequestAdapter") 783 @NativeClassQualifiedName("CronetURLRequestAdapter")
757 private native boolean nativeReadData( 784 private native boolean nativeReadData(
758 long nativePtr, ByteBuffer byteBuffer, int position, int capacity); 785 long nativePtr, ByteBuffer byteBuffer, int position, int capacity);
759 786
760 @NativeClassQualifiedName("CronetURLRequestAdapter") 787 @NativeClassQualifiedName("CronetURLRequestAdapter")
761 private native void nativeDestroy(long nativePtr, boolean sendOnCanceled); 788 private native void nativeDestroy(long nativePtr, boolean sendOnCanceled);
762 789
763 @NativeClassQualifiedName("CronetURLRequestAdapter") 790 @NativeClassQualifiedName("CronetURLRequestAdapter")
764 private native void nativeGetStatus(long nativePtr, UrlRequest.StatusListene r listener); 791 private native void nativeGetStatus(long nativePtr, UrlRequest.StatusListene r listener);
765 } 792 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698