OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
216 throw new IllegalArgumentException( | 220 throw new IllegalArgumentException( |
217 "Invalid header " + header.getKey() + "=" + head er.getValue()); | 221 "Invalid header " + header.getKey() + "=" + head er.getValue()); |
218 } | 222 } |
219 } | 223 } |
220 if (mUploadDataStream != null) { | 224 if (mUploadDataStream != null) { |
221 if (!hasContentType) { | 225 if (!hasContentType) { |
222 throw new IllegalArgumentException( | 226 throw new IllegalArgumentException( |
223 "Requests with upload data must have a Content-T ype."); | 227 "Requests with upload data must have a Content-T ype."); |
224 } | 228 } |
225 mStarted = true; | 229 mStarted = true; |
226 mUploadDataStream.postTaskToExecutor(new Runnable() { | 230 mUploadDataStream.initializeWithRequest(CronetUrlRequest.thi s, new Runnable() { |
227 @Override | 231 @Override |
228 public void run() { | 232 public void run() { |
229 mUploadDataStream.initializeWithRequest(CronetUrlReq uest.this); | |
230 synchronized (mUrlRequestAdapterLock) { | 233 synchronized (mUrlRequestAdapterLock) { |
231 if (isDoneLocked()) { | 234 if (isDoneLocked()) { |
232 return; | 235 return; |
233 } | 236 } |
234 mUploadDataStream.attachNativeAdapterToRequest(m UrlRequestAdapter); | 237 mUploadDataStream.attachNativeAdapterToRequest(m UrlRequestAdapter); |
235 startInternalLocked(); | 238 startInternalLocked(); |
236 } | 239 } |
237 } | 240 } |
238 }); | 241 }); |
239 return; | 242 return; |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
360 /** | 363 /** |
361 * Posts task to application Executor. Used for Listener callbacks | 364 * Posts task to application Executor. Used for Listener callbacks |
362 * and other tasks that should not be executed on network thread. | 365 * and other tasks that should not be executed on network thread. |
363 */ | 366 */ |
364 private void postTaskToExecutor(Runnable task) { | 367 private void postTaskToExecutor(Runnable task) { |
365 try { | 368 try { |
366 mExecutor.execute(task); | 369 mExecutor.execute(task); |
367 } catch (RejectedExecutionException failException) { | 370 } catch (RejectedExecutionException failException) { |
368 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex ecutor", | 371 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex ecutor", |
369 failException); | 372 failException); |
370 // If posting a task throws an exception, then there is no choice | 373 // 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. | 374 // be permanent (executor shutdown), transient (AbortPolicy, or Call erRunsPolicy with |
372 destroyRequestAdapter(false); | 375 // direct execution not permitted), or caused the the runnables we s ubmit if |
mef
2016/08/31 20:24:25
nit: the the -> by the?
Charles
2016/08/31 22:36:41
Done.
| |
376 // mUserExecutor is a direct executor and direct execution is not pe rmitted. In the | |
377 // latter two cases, we at least have a chance to inform the embedde r of the request's | |
mef
2016/08/31 20:24:25
nit: We don't use 'we' in Chromium comments. :)
Charles
2016/08/31 22:36:41
Done.
| |
378 // failure, since failWithException does not enforce that onFailed() is not executed | |
379 // inline. | |
380 failWithException( | |
381 new UrlRequestException("Exception posting task to executor" , failException)); | |
373 } | 382 } |
374 } | 383 } |
375 | 384 |
376 private static int convertRequestPriority(int priority) { | 385 private static int convertRequestPriority(int priority) { |
377 switch (priority) { | 386 switch (priority) { |
378 case Builder.REQUEST_PRIORITY_IDLE: | 387 case Builder.REQUEST_PRIORITY_IDLE: |
379 return RequestPriority.IDLE; | 388 return RequestPriority.IDLE; |
380 case Builder.REQUEST_PRIORITY_LOWEST: | 389 case Builder.REQUEST_PRIORITY_LOWEST: |
381 return RequestPriority.LOWEST; | 390 return RequestPriority.LOWEST; |
382 case Builder.REQUEST_PRIORITY_LOW: | 391 case Builder.REQUEST_PRIORITY_LOW: |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
430 | 439 |
431 /** | 440 /** |
432 * If callback method throws an exception, request gets canceled | 441 * If callback method throws an exception, request gets canceled |
433 * and exception is reported via onFailed listener callback. | 442 * and exception is reported via onFailed listener callback. |
434 * Only called on the Executor. | 443 * Only called on the Executor. |
435 */ | 444 */ |
436 private void onCallbackException(Exception e) { | 445 private void onCallbackException(Exception e) { |
437 UrlRequestException requestError = | 446 UrlRequestException requestError = |
438 new UrlRequestException("Exception received from UrlRequest.Call back", e); | 447 new UrlRequestException("Exception received from UrlRequest.Call back", e); |
439 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in CalledByNative meth od", e); | 448 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in CalledByNative meth od", e); |
440 // Do not call into listener if request is finished. | 449 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 } | 450 } |
454 | 451 |
455 /** | 452 /** |
456 * Called when UploadDataProvider encounters an error. | 453 * Called when UploadDataProvider encounters an error. |
457 */ | 454 */ |
458 void onUploadException(Throwable e) { | 455 void onUploadException(Throwable e) { |
459 UrlRequestException uploadError = | 456 UrlRequestException uploadError = |
460 new UrlRequestException("Exception received from UploadDataProvi der", e); | 457 new UrlRequestException("Exception received from UploadDataProvi der", e); |
461 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in upload method", e); | 458 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in upload method", e); |
462 failWithException(uploadError); | 459 failWithException(uploadError); |
463 } | 460 } |
464 | 461 |
465 /** | 462 /** |
466 * Fails the request with an exception. Can be called on any thread. | 463 * Fails the request with an exception. Can be called on any thread. |
467 */ | 464 */ |
468 private void failWithException(final UrlRequestException exception) { | 465 private void failWithException(final UrlRequestException exception) { |
466 synchronized (mUrlRequestAdapterLock) { | |
467 if (isDoneLocked()) { | |
468 return; | |
469 } | |
470 destroyRequestAdapter(false); | |
471 } | |
469 Runnable task = new Runnable() { | 472 Runnable task = new Runnable() { |
470 @Override | 473 @Override |
471 public void run() { | 474 public void run() { |
472 synchronized (mUrlRequestAdapterLock) { | |
473 if (isDoneLocked()) { | |
474 return; | |
475 } | |
476 destroyRequestAdapter(false); | |
477 } | |
478 try { | 475 try { |
479 mCallback.onFailed(CronetUrlRequest.this, mResponseInfo, exc eption); | 476 mCallback.onFailed(CronetUrlRequest.this, mResponseInfo, exc eption); |
480 } catch (Exception e) { | 477 } catch (Exception e) { |
481 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onError method", e); | 478 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onFaile d method", e); |
482 } | 479 } |
483 } | 480 } |
484 }; | 481 }; |
485 postTaskToExecutor(task); | 482 try { |
483 mExecutor.execute(task); | |
484 } catch (RejectedExecutionException e) { | |
485 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex ecutor", e); | |
486 } | |
486 } | 487 } |
487 | 488 |
488 //////////////////////////////////////////////// | 489 //////////////////////////////////////////////// |
489 // Private methods called by the native code. | 490 // Private methods called by the native code. |
490 // Always called on network thread. | 491 // Always called on network thread. |
491 //////////////////////////////////////////////// | 492 //////////////////////////////////////////////// |
492 | 493 |
493 /** | 494 /** |
494 * Called before following redirects. The redirect will only be followed if | 495 * 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. | 496 * {@link #followRedirect()} is called. If the redirect response has a body, it will be ignored. |
(...skipping 14 matching lines...) Expand all Loading... | |
510 httpStatusText, headers, wasCached, negotiatedProtocol, proxySer ver); | 511 httpStatusText, headers, wasCached, negotiatedProtocol, proxySer ver); |
511 mReceivedBytesCountFromRedirects += receivedBytesCount; | 512 mReceivedBytesCountFromRedirects += receivedBytesCount; |
512 responseInfo.setReceivedBytesCount(mReceivedBytesCountFromRedirects); | 513 responseInfo.setReceivedBytesCount(mReceivedBytesCountFromRedirects); |
513 | 514 |
514 // Have to do this after creating responseInfo. | 515 // Have to do this after creating responseInfo. |
515 mUrlChain.add(newLocation); | 516 mUrlChain.add(newLocation); |
516 | 517 |
517 Runnable task = new Runnable() { | 518 Runnable task = new Runnable() { |
518 @Override | 519 @Override |
519 public void run() { | 520 public void run() { |
521 checkCallingThread(); | |
520 synchronized (mUrlRequestAdapterLock) { | 522 synchronized (mUrlRequestAdapterLock) { |
521 if (isDoneLocked()) { | 523 if (isDoneLocked()) { |
522 return; | 524 return; |
523 } | 525 } |
524 mWaitingOnRedirect = true; | 526 mWaitingOnRedirect = true; |
525 } | 527 } |
526 | 528 |
527 try { | 529 try { |
528 mCallback.onRedirectReceived(CronetUrlRequest.this, response Info, newLocation); | 530 mCallback.onRedirectReceived(CronetUrlRequest.this, response Info, newLocation); |
529 } catch (Exception e) { | 531 } catch (Exception e) { |
(...skipping 10 matching lines...) Expand all Loading... | |
540 */ | 542 */ |
541 @SuppressWarnings("unused") | 543 @SuppressWarnings("unused") |
542 @CalledByNative | 544 @CalledByNative |
543 private void onResponseStarted(int httpStatusCode, String httpStatusText, St ring[] headers, | 545 private void onResponseStarted(int httpStatusCode, String httpStatusText, St ring[] headers, |
544 boolean wasCached, String negotiatedProtocol, String proxyServer) { | 546 boolean wasCached, String negotiatedProtocol, String proxyServer) { |
545 mResponseInfo = prepareResponseInfoOnNetworkThread(httpStatusCode, httpS tatusText, headers, | 547 mResponseInfo = prepareResponseInfoOnNetworkThread(httpStatusCode, httpS tatusText, headers, |
546 wasCached, negotiatedProtocol, proxyServer); | 548 wasCached, negotiatedProtocol, proxyServer); |
547 Runnable task = new Runnable() { | 549 Runnable task = new Runnable() { |
548 @Override | 550 @Override |
549 public void run() { | 551 public void run() { |
552 checkCallingThread(); | |
550 synchronized (mUrlRequestAdapterLock) { | 553 synchronized (mUrlRequestAdapterLock) { |
551 if (isDoneLocked()) { | 554 if (isDoneLocked()) { |
552 return; | 555 return; |
553 } | 556 } |
554 if (mRequestMetricsAccumulator != null) { | 557 if (mRequestMetricsAccumulator != null) { |
555 mRequestMetricsAccumulator.onResponseStarted(); | 558 mRequestMetricsAccumulator.onResponseStarted(); |
556 } | 559 } |
557 mWaitingOnRead = true; | 560 mWaitingOnRead = true; |
558 } | 561 } |
559 | 562 |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
729 } | 732 } |
730 } | 733 } |
731 | 734 |
732 private void onResponseStarted() { | 735 private void onResponseStarted() { |
733 if (mRequestStartTime != null && mTtfbMs == null) { | 736 if (mRequestStartTime != null && mTtfbMs == null) { |
734 mTtfbMs = SystemClock.elapsedRealtime() - mRequestStartTime; | 737 mTtfbMs = SystemClock.elapsedRealtime() - mRequestStartTime; |
735 } | 738 } |
736 } | 739 } |
737 } | 740 } |
738 | 741 |
742 /** Enforces prohibition of direct execution. */ | |
743 private void checkCallingThread() { | |
744 if (!mAllowDirectExecutor && mRequestContext.isNetworkThread(Thread.curr entThread())) { | |
745 throw new InlineExecutionProhibitedException(); | |
746 } | |
747 } | |
748 | |
739 // Native methods are implemented in cronet_url_request_adapter.cc. | 749 // Native methods are implemented in cronet_url_request_adapter.cc. |
740 | 750 |
741 private native long nativeCreateRequestAdapter(long urlRequestContextAdapter , String url, | 751 private native long nativeCreateRequestAdapter(long urlRequestContextAdapter , String url, |
742 int priority, boolean disableCache, boolean disableConnectionMigrati on); | 752 int priority, boolean disableCache, boolean disableConnectionMigrati on); |
743 | 753 |
744 @NativeClassQualifiedName("CronetURLRequestAdapter") | 754 @NativeClassQualifiedName("CronetURLRequestAdapter") |
745 private native boolean nativeSetHttpMethod(long nativePtr, String method); | 755 private native boolean nativeSetHttpMethod(long nativePtr, String method); |
746 | 756 |
747 @NativeClassQualifiedName("CronetURLRequestAdapter") | 757 @NativeClassQualifiedName("CronetURLRequestAdapter") |
748 private native boolean nativeAddRequestHeader(long nativePtr, String name, S tring value); | 758 private native boolean nativeAddRequestHeader(long nativePtr, String name, S tring value); |
749 | 759 |
750 @NativeClassQualifiedName("CronetURLRequestAdapter") | 760 @NativeClassQualifiedName("CronetURLRequestAdapter") |
751 private native void nativeStart(long nativePtr); | 761 private native void nativeStart(long nativePtr); |
752 | 762 |
753 @NativeClassQualifiedName("CronetURLRequestAdapter") | 763 @NativeClassQualifiedName("CronetURLRequestAdapter") |
754 private native void nativeFollowDeferredRedirect(long nativePtr); | 764 private native void nativeFollowDeferredRedirect(long nativePtr); |
755 | 765 |
756 @NativeClassQualifiedName("CronetURLRequestAdapter") | 766 @NativeClassQualifiedName("CronetURLRequestAdapter") |
757 private native boolean nativeReadData( | 767 private native boolean nativeReadData( |
758 long nativePtr, ByteBuffer byteBuffer, int position, int capacity); | 768 long nativePtr, ByteBuffer byteBuffer, int position, int capacity); |
759 | 769 |
760 @NativeClassQualifiedName("CronetURLRequestAdapter") | 770 @NativeClassQualifiedName("CronetURLRequestAdapter") |
761 private native void nativeDestroy(long nativePtr, boolean sendOnCanceled); | 771 private native void nativeDestroy(long nativePtr, boolean sendOnCanceled); |
762 | 772 |
763 @NativeClassQualifiedName("CronetURLRequestAdapter") | 773 @NativeClassQualifiedName("CronetURLRequestAdapter") |
764 private native void nativeGetStatus(long nativePtr, UrlRequest.StatusListene r listener); | 774 private native void nativeGetStatus(long nativePtr, UrlRequest.StatusListene r listener); |
765 } | 775 } |
OLD | NEW |