| 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 org.chromium.base.Log; | 7 import org.chromium.base.Log; |
| 8 import org.chromium.base.VisibleForTesting; | 8 import org.chromium.base.VisibleForTesting; |
| 9 import org.chromium.base.annotations.CalledByNative; | 9 import org.chromium.base.annotations.CalledByNative; |
| 10 import org.chromium.base.annotations.JNIAdditionalImport; | 10 import org.chromium.base.annotations.JNIAdditionalImport; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 @JNIAdditionalImport(VersionSafeCallbacks.class) | 44 @JNIAdditionalImport(VersionSafeCallbacks.class) |
| 45 @VisibleForTesting | 45 @VisibleForTesting |
| 46 public final class CronetUrlRequest extends UrlRequestBase { | 46 public final class CronetUrlRequest extends UrlRequestBase { |
| 47 private final boolean mAllowDirectExecutor; | 47 private final boolean mAllowDirectExecutor; |
| 48 | 48 |
| 49 /* Native adapter object, owned by UrlRequest. */ | 49 /* Native adapter object, owned by UrlRequest. */ |
| 50 @GuardedBy("mUrlRequestAdapterLock") | 50 @GuardedBy("mUrlRequestAdapterLock") |
| 51 private long mUrlRequestAdapter; | 51 private long mUrlRequestAdapter; |
| 52 | 52 |
| 53 @GuardedBy("mUrlRequestAdapterLock") | 53 @GuardedBy("mUrlRequestAdapterLock") |
| 54 private boolean mStarted = false; | 54 private boolean mStarted; |
| 55 @GuardedBy("mUrlRequestAdapterLock") | 55 @GuardedBy("mUrlRequestAdapterLock") |
| 56 private boolean mWaitingOnRedirect = false; | 56 private boolean mWaitingOnRedirect; |
| 57 @GuardedBy("mUrlRequestAdapterLock") | 57 @GuardedBy("mUrlRequestAdapterLock") |
| 58 private boolean mWaitingOnRead = false; | 58 private boolean mWaitingOnRead; |
| 59 @GuardedBy("mUrlRequestAdapterLock") | |
| 60 private RequestFinishedInfo.Metrics mMetrics; | |
| 61 | 59 |
| 62 /* | 60 /* |
| 63 * Synchronize access to mUrlRequestAdapter, mStarted, mWaitingOnRedirect, | 61 * Synchronize access to mUrlRequestAdapter, mStarted, mWaitingOnRedirect, |
| 64 * and mWaitingOnRead. | 62 * and mWaitingOnRead. |
| 65 */ | 63 */ |
| 66 private final Object mUrlRequestAdapterLock = new Object(); | 64 private final Object mUrlRequestAdapterLock = new Object(); |
| 67 private final CronetUrlRequestContext mRequestContext; | 65 private final CronetUrlRequestContext mRequestContext; |
| 68 private final Executor mExecutor; | 66 private final Executor mExecutor; |
| 69 | 67 |
| 70 /* | 68 /* |
| 71 * URL chain contains the URL currently being requested, and | 69 * URL chain contains the URL currently being requested, and |
| 72 * all URLs previously requested. New URLs are added before | 70 * all URLs previously requested. New URLs are added before |
| 73 * mCallback.onRedirectReceived is called. | 71 * mCallback.onRedirectReceived is called. |
| 74 */ | 72 */ |
| 75 private final List<String> mUrlChain = new ArrayList<String>(); | 73 private final List<String> mUrlChain = new ArrayList<String>(); |
| 76 private long mReceivedByteCountFromRedirects; | 74 private long mReceivedByteCountFromRedirects; |
| 77 | 75 |
| 78 private final VersionSafeCallbacks.UrlRequestCallback mCallback; | 76 private final VersionSafeCallbacks.UrlRequestCallback mCallback; |
| 79 private final String mInitialUrl; | 77 private final String mInitialUrl; |
| 80 private final int mPriority; | 78 private final int mPriority; |
| 81 private String mInitialMethod; | 79 private String mInitialMethod; |
| 82 private final HeadersList mRequestHeaders = new HeadersList(); | 80 private final HeadersList mRequestHeaders = new HeadersList(); |
| 83 private final Collection<Object> mRequestAnnotations; | 81 private final Collection<Object> mRequestAnnotations; |
| 84 @RequestFinishedInfoImpl.FinishedReason | |
| 85 private int mFinishedReason; | |
| 86 private CronetException mException; | |
| 87 private final boolean mDisableCache; | 82 private final boolean mDisableCache; |
| 88 private final boolean mDisableConnectionMigration; | 83 private final boolean mDisableConnectionMigration; |
| 89 | 84 |
| 90 private CronetUploadDataStream mUploadDataStream; | 85 private CronetUploadDataStream mUploadDataStream; |
| 91 | 86 |
| 92 private UrlResponseInfoImpl mResponseInfo; | 87 private UrlResponseInfoImpl mResponseInfo; |
| 93 | 88 |
| 89 // mFinishedReason and mException should only be updated once with mUrlReque
stAdapterLock held. |
| 90 // They are read on executor's thread after the last update. |
| 91 @RequestFinishedInfoImpl.FinishedReason |
| 92 private int mFinishedReason; |
| 93 private CronetException mException; |
| 94 |
| 95 // Accessed only from the network thread. |
| 96 private boolean mMetricsCollected; |
| 97 |
| 94 /* | 98 /* |
| 95 * Listener callback is repeatedly invoked when each read is completed, so i
t | 99 * Listener callback is repeatedly invoked when each read is completed, so i
t |
| 96 * is cached as a member variable. | 100 * is cached as a member variable. |
| 97 */ | 101 */ |
| 98 private OnReadCompletedRunnable mOnReadCompletedTask; | 102 private OnReadCompletedRunnable mOnReadCompletedTask; |
| 99 | 103 |
| 100 private Runnable mOnDestroyedCallbackForTesting; | 104 private Runnable mOnDestroyedCallbackForTesting; |
| 101 | 105 |
| 102 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>> {} |
| 103 | 107 |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 } | 232 } |
| 229 mUploadDataStream.attachNativeAdapterToRequest(m
UrlRequestAdapter); | 233 mUploadDataStream.attachNativeAdapterToRequest(m
UrlRequestAdapter); |
| 230 startInternalLocked(); | 234 startInternalLocked(); |
| 231 } | 235 } |
| 232 } | 236 } |
| 233 }); | 237 }); |
| 234 return; | 238 return; |
| 235 } | 239 } |
| 236 } catch (RuntimeException e) { | 240 } catch (RuntimeException e) { |
| 237 // If there's an exception, cleanup and then throw the | 241 // If there's an exception, cleanup and then throw the |
| 238 // exception to the caller. | 242 // exception to the caller. Use null here to avoid rethrowing |
| 239 destroyRequestAdapter(false); | 243 // in onDestroyed(). |
| 244 failWithExceptionFromJava(null); |
| 240 throw e; | 245 throw e; |
| 241 } | 246 } |
| 242 mStarted = true; | 247 mStarted = true; |
| 243 startInternalLocked(); | 248 startInternalLocked(); |
| 244 } | 249 } |
| 245 } | 250 } |
| 246 | 251 |
| 247 /* | 252 /* |
| 248 * Starts fully configured request. Could execute on UploadDataProvider exec
utor. | 253 * Starts fully configured request. Could execute on UploadDataProvider exec
utor. |
| 249 * Caller is expected to ensure that request isn't canceled and mUrlRequestA
dapter is valid. | 254 * Caller is expected to ensure that request isn't canceled and mUrlRequestA
dapter is valid. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 } | 296 } |
| 292 } | 297 } |
| 293 } | 298 } |
| 294 | 299 |
| 295 @Override | 300 @Override |
| 296 public void cancel() { | 301 public void cancel() { |
| 297 synchronized (mUrlRequestAdapterLock) { | 302 synchronized (mUrlRequestAdapterLock) { |
| 298 if (isDoneLocked() || !mStarted) { | 303 if (isDoneLocked() || !mStarted) { |
| 299 return; | 304 return; |
| 300 } | 305 } |
| 301 destroyRequestAdapter(true); | 306 nativeCancel(mUrlRequestAdapter); |
| 302 } | 307 } |
| 303 } | 308 } |
| 304 | 309 |
| 305 @Override | 310 @Override |
| 306 public boolean isDone() { | 311 public boolean isDone() { |
| 307 synchronized (mUrlRequestAdapterLock) { | 312 synchronized (mUrlRequestAdapterLock) { |
| 308 return isDoneLocked(); | 313 return isDoneLocked(); |
| 309 } | 314 } |
| 310 } | 315 } |
| 311 | 316 |
| 317 private void setIsDone( |
| 318 CronetException exception, @RequestFinishedInfoImpl.FinishedReason i
nt finishedReason) { |
| 319 synchronized (mUrlRequestAdapterLock) { |
| 320 assert mUrlRequestAdapter != 0; |
| 321 assert mException == null; |
| 322 mException = exception; |
| 323 mFinishedReason = finishedReason; |
| 324 assert mException == null || mFinishedReason == RequestFinishedInfo.
FAILED; |
| 325 mRequestContext.onRequestDestroyed(); |
| 326 mUrlRequestAdapter = 0; |
| 327 } |
| 328 } |
| 329 |
| 312 @GuardedBy("mUrlRequestAdapterLock") | 330 @GuardedBy("mUrlRequestAdapterLock") |
| 313 private boolean isDoneLocked() { | 331 private boolean isDoneLocked() { |
| 314 return mStarted && mUrlRequestAdapter == 0; | 332 return mStarted && mUrlRequestAdapter == 0; |
| 315 } | 333 } |
| 316 | 334 |
| 317 @Override | 335 @Override |
| 318 public void getStatus(UrlRequest.StatusListener unsafeListener) { | 336 public void getStatus(UrlRequest.StatusListener unsafeListener) { |
| 319 final VersionSafeCallbacks.UrlRequestStatusListener listener = | 337 final VersionSafeCallbacks.UrlRequestStatusListener listener = |
| 320 new VersionSafeCallbacks.UrlRequestStatusListener(unsafeListener
); | 338 new VersionSafeCallbacks.UrlRequestStatusListener(unsafeListener
); |
| 321 synchronized (mUrlRequestAdapterLock) { | 339 synchronized (mUrlRequestAdapterLock) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 } catch (RejectedExecutionException failException) { | 379 } catch (RejectedExecutionException failException) { |
| 362 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex
ecutor", | 380 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex
ecutor", |
| 363 failException); | 381 failException); |
| 364 // If posting a task throws an exception, then we fail the request.
This exception could | 382 // If posting a task throws an exception, then we fail the request.
This exception could |
| 365 // be permanent (executor shutdown), transient (AbortPolicy, or Call
erRunsPolicy with | 383 // be permanent (executor shutdown), transient (AbortPolicy, or Call
erRunsPolicy with |
| 366 // direct execution not permitted), or caused by the runnables we su
bmit if | 384 // direct execution not permitted), or caused by the runnables we su
bmit if |
| 367 // mUserExecutor is a direct executor and direct execution is not pe
rmitted. In the | 385 // mUserExecutor is a direct executor and direct execution is not pe
rmitted. In the |
| 368 // latter two cases, there is at least have a chance to inform the e
mbedder of the | 386 // latter two cases, there is at least have a chance to inform the e
mbedder of the |
| 369 // request's failure, since failWithException does not enforce that
onFailed() is not | 387 // request's failure, since failWithException does not enforce that
onFailed() is not |
| 370 // executed inline. | 388 // executed inline. |
| 371 failWithException( | 389 failWithExceptionFromJava( |
| 372 new CronetExceptionImpl("Exception posting task to executor"
, failException)); | 390 new CronetExceptionImpl("Exception posting task to executor"
, failException)); |
| 373 } | 391 } |
| 374 } | 392 } |
| 375 | 393 |
| 376 private static int convertRequestPriority(int priority) { | 394 private static int convertRequestPriority(int priority) { |
| 377 switch (priority) { | 395 switch (priority) { |
| 378 case Builder.REQUEST_PRIORITY_IDLE: | 396 case Builder.REQUEST_PRIORITY_IDLE: |
| 379 return RequestPriority.IDLE; | 397 return RequestPriority.IDLE; |
| 380 case Builder.REQUEST_PRIORITY_LOWEST: | 398 case Builder.REQUEST_PRIORITY_LOWEST: |
| 381 return RequestPriority.LOWEST; | 399 return RequestPriority.LOWEST; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 403 } | 421 } |
| 404 | 422 |
| 405 private void checkNotStarted() { | 423 private void checkNotStarted() { |
| 406 synchronized (mUrlRequestAdapterLock) { | 424 synchronized (mUrlRequestAdapterLock) { |
| 407 if (mStarted || isDoneLocked()) { | 425 if (mStarted || isDoneLocked()) { |
| 408 throw new IllegalStateException("Request is already started."); | 426 throw new IllegalStateException("Request is already started."); |
| 409 } | 427 } |
| 410 } | 428 } |
| 411 } | 429 } |
| 412 | 430 |
| 413 private void destroyRequestAdapter(boolean sendOnCanceled) { | |
| 414 synchronized (mUrlRequestAdapterLock) { | |
| 415 if (mUrlRequestAdapter == 0) { | |
| 416 return; | |
| 417 } | |
| 418 nativeDestroy(mUrlRequestAdapter, sendOnCanceled); | |
| 419 mRequestContext.onRequestDestroyed(); | |
| 420 mUrlRequestAdapter = 0; | |
| 421 if (mOnDestroyedCallbackForTesting != null) { | |
| 422 mOnDestroyedCallbackForTesting.run(); | |
| 423 } | |
| 424 } | |
| 425 } | |
| 426 | |
| 427 /** | 431 /** |
| 428 * If callback method throws an exception, request gets canceled | 432 * If callback method throws an exception, request gets canceled |
| 429 * and exception is reported via onFailed listener callback. | 433 * and exception is reported via onFailed listener callback. |
| 430 * Only called on the Executor. | 434 * Only called on the Executor. |
| 431 */ | 435 */ |
| 432 private void onCallbackException(Exception e) { | 436 private void onCallbackException(Exception e) { |
| 433 CallbackException requestError = | 437 CallbackException requestError = |
| 434 new CallbackExceptionImpl("Exception received from UrlRequest.Ca
llback", e); | 438 new CallbackExceptionImpl("Exception received from UrlRequest.Ca
llback", e); |
| 435 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in CalledByNative meth
od", e); | 439 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in CalledByNative meth
od", e); |
| 436 failWithException(requestError); | 440 failWithExceptionFromJava(requestError); |
| 437 } | 441 } |
| 438 | 442 |
| 439 /** | 443 /** |
| 440 * Called when UploadDataProvider encounters an error. | 444 * Called when UploadDataProvider encounters an error. |
| 441 */ | 445 */ |
| 442 void onUploadException(Throwable e) { | 446 void onUploadException(Throwable e) { |
| 443 CallbackException uploadError = | 447 CallbackException uploadError = |
| 444 new CallbackExceptionImpl("Exception received from UploadDataPro
vider", e); | 448 new CallbackExceptionImpl("Exception received from UploadDataPro
vider", e); |
| 445 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in upload method", e); | 449 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in upload method", e); |
| 446 failWithException(uploadError); | 450 failWithExceptionFromJava(uploadError); |
| 447 } | 451 } |
| 448 | 452 |
| 449 /** | 453 /** |
| 450 * Fails the request with an exception. Can be called on any thread. | 454 * Fails the request with an exception on any thread. This method should onl
y be used when error |
| 455 * originates from Java. |
| 451 */ | 456 */ |
| 452 private void failWithException(final CronetException exception) { | 457 private void failWithExceptionFromJava(final CronetException exception) { |
| 453 mException = exception; | |
| 454 synchronized (mUrlRequestAdapterLock) { | 458 synchronized (mUrlRequestAdapterLock) { |
| 455 if (isDoneLocked()) { | 459 if (isDoneLocked()) { |
| 456 return; | 460 return; |
| 457 } | 461 } |
| 458 destroyRequestAdapter(false); | 462 nativeDestroy(mUrlRequestAdapter); |
| 459 } | 463 setIsDone(exception, RequestFinishedInfo.FAILED); |
| 460 Runnable task = new Runnable() { | |
| 461 @Override | |
| 462 public void run() { | |
| 463 try { | |
| 464 mCallback.onFailed(CronetUrlRequest.this, mResponseInfo, exc
eption); | |
| 465 } catch (Exception e) { | |
| 466 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onFaile
d method", e); | |
| 467 } | |
| 468 } | |
| 469 }; | |
| 470 try { | |
| 471 mExecutor.execute(task); | |
| 472 } catch (RejectedExecutionException e) { | |
| 473 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex
ecutor", e); | |
| 474 } | 464 } |
| 475 } | 465 } |
| 476 | 466 |
| 477 //////////////////////////////////////////////// | 467 //////////////////////////////////////////////// |
| 478 // Private methods called by the native code. | 468 // Private methods called by the native code. |
| 479 // Always called on network thread. | 469 // Always called on network thread. |
| 480 //////////////////////////////////////////////// | 470 //////////////////////////////////////////////// |
| 481 | 471 |
| 482 /** | 472 /** |
| 483 * Called before following redirects. The redirect will only be followed if | 473 * Called before following redirects. The redirect will only be followed if |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 * read(). Used as a minimal check that the buffer hasn't been | 562 * read(). Used as a minimal check that the buffer hasn't been |
| 573 * modified while reading from the network. | 563 * modified while reading from the network. |
| 574 * @param receivedByteCount number of bytes received. | 564 * @param receivedByteCount number of bytes received. |
| 575 */ | 565 */ |
| 576 @SuppressWarnings("unused") | 566 @SuppressWarnings("unused") |
| 577 @CalledByNative | 567 @CalledByNative |
| 578 private void onReadCompleted(final ByteBuffer byteBuffer, int bytesRead, int
initialPosition, | 568 private void onReadCompleted(final ByteBuffer byteBuffer, int bytesRead, int
initialPosition, |
| 579 int initialLimit, long receivedByteCount) { | 569 int initialLimit, long receivedByteCount) { |
| 580 mResponseInfo.setReceivedByteCount(mReceivedByteCountFromRedirects + rec
eivedByteCount); | 570 mResponseInfo.setReceivedByteCount(mReceivedByteCountFromRedirects + rec
eivedByteCount); |
| 581 if (byteBuffer.position() != initialPosition || byteBuffer.limit() != in
itialLimit) { | 571 if (byteBuffer.position() != initialPosition || byteBuffer.limit() != in
itialLimit) { |
| 582 failWithException( | 572 failWithExceptionFromJava( |
| 583 new CronetExceptionImpl("ByteBuffer modified externally duri
ng read", null)); | 573 new CronetExceptionImpl("ByteBuffer modified externally duri
ng read", null)); |
| 584 return; | 574 return; |
| 585 } | 575 } |
| 586 if (mOnReadCompletedTask == null) { | 576 if (mOnReadCompletedTask == null) { |
| 587 mOnReadCompletedTask = new OnReadCompletedRunnable(); | 577 mOnReadCompletedTask = new OnReadCompletedRunnable(); |
| 588 } | 578 } |
| 589 byteBuffer.position(initialPosition + bytesRead); | 579 byteBuffer.position(initialPosition + bytesRead); |
| 590 mOnReadCompletedTask.mByteBuffer = byteBuffer; | 580 mOnReadCompletedTask.mByteBuffer = byteBuffer; |
| 591 postTaskToExecutor(mOnReadCompletedTask); | 581 postTaskToExecutor(mOnReadCompletedTask); |
| 592 } | 582 } |
| 593 | 583 |
| 594 /** | 584 /** |
| 595 * Called when request is completed successfully, no callbacks will be | 585 * Called when request is completed successfully, no callbacks will be |
| 596 * called afterwards. | 586 * called afterwards. |
| 597 * | 587 * |
| 598 * @param receivedByteCount number of bytes received. | 588 * @param receivedByteCount number of bytes received. |
| 599 */ | 589 */ |
| 600 @SuppressWarnings("unused") | 590 @SuppressWarnings("unused") |
| 601 @CalledByNative | 591 @CalledByNative |
| 602 private void onSucceeded(long receivedByteCount) { | 592 private void onSucceeded(long receivedByteCount) { |
| 603 mFinishedReason = RequestFinishedInfo.SUCCEEDED; | 593 setIsDone(null, RequestFinishedInfo.SUCCEEDED); |
| 604 mResponseInfo.setReceivedByteCount(mReceivedByteCountFromRedirects + rec
eivedByteCount); | 594 mResponseInfo.setReceivedByteCount(mReceivedByteCountFromRedirects + rec
eivedByteCount); |
| 605 Runnable task = new Runnable() { | 595 Runnable task = new Runnable() { |
| 606 @Override | 596 @Override |
| 607 public void run() { | 597 public void run() { |
| 608 synchronized (mUrlRequestAdapterLock) { | |
| 609 if (isDoneLocked()) { | |
| 610 return; | |
| 611 } | |
| 612 // Destroy adapter first, so request context could be shut | |
| 613 // down from the listener. | |
| 614 destroyRequestAdapter(false); | |
| 615 } | |
| 616 try { | 598 try { |
| 617 mCallback.onSucceeded(CronetUrlRequest.this, mResponseInfo); | 599 mCallback.onSucceeded(CronetUrlRequest.this, mResponseInfo); |
| 618 } catch (Exception e) { | 600 } catch (Exception e) { |
| 619 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onCompl
ete method", e); | 601 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onCompl
ete method", e); |
| 620 } | 602 } |
| 621 } | 603 } |
| 622 }; | 604 }; |
| 623 postTaskToExecutor(task); | 605 postTaskToExecutor(task); |
| 624 } | 606 } |
| 625 | 607 |
| 626 /** | 608 /** |
| 627 * Called when error has occured, no callbacks will be called afterwards. | 609 * Called when error has occured, no callbacks will be called afterwards. |
| 628 * | 610 * |
| 629 * @param errorCode Error code represented by {@code UrlRequestError} that s
hould be mapped | 611 * @param errorCode Error code represented by {@code UrlRequestError} that s
hould be mapped |
| 630 * to one of {@link NetworkException#ERROR_HOSTNAME_NOT_RES
OLVED | 612 * to one of {@link NetworkException#ERROR_HOSTNAME_NOT_RES
OLVED |
| 631 * NetworkException.ERROR_*}. | 613 * NetworkException.ERROR_*}. |
| 632 * @param nativeError native net error code. | 614 * @param nativeError native net error code. |
| 633 * @param errorString textual representation of the error code. | 615 * @param errorString textual representation of the error code. |
| 634 * @param receivedByteCount number of bytes received. | 616 * @param receivedByteCount number of bytes received. |
| 635 */ | 617 */ |
| 636 @SuppressWarnings("unused") | 618 @SuppressWarnings("unused") |
| 637 @CalledByNative | 619 @CalledByNative |
| 638 private void onError(int errorCode, int nativeError, int nativeQuicError, St
ring errorString, | 620 private void onError(int errorCode, int nativeError, int nativeQuicError, St
ring errorString, |
| 639 long receivedByteCount) { | 621 long receivedByteCount) { |
| 640 mFinishedReason = RequestFinishedInfo.FAILED; | |
| 641 if (mResponseInfo != null) { | 622 if (mResponseInfo != null) { |
| 642 mResponseInfo.setReceivedByteCount(mReceivedByteCountFromRedirects +
receivedByteCount); | 623 mResponseInfo.setReceivedByteCount(mReceivedByteCountFromRedirects +
receivedByteCount); |
| 643 } | 624 } |
| 625 CronetException exception; |
| 644 if (errorCode == NetworkException.ERROR_QUIC_PROTOCOL_FAILED) { | 626 if (errorCode == NetworkException.ERROR_QUIC_PROTOCOL_FAILED) { |
| 645 failWithException(new QuicExceptionImpl( | 627 exception = new QuicExceptionImpl( |
| 646 "Exception in CronetUrlRequest: " + errorString, nativeError
, nativeQuicError)); | 628 "Exception in CronetUrlRequest: " + errorString, nativeError
, nativeQuicError); |
| 647 } else { | 629 } else { |
| 648 int javaError = mapUrlRequestErrorToApiErrorCode(errorCode); | 630 int javaError = mapUrlRequestErrorToApiErrorCode(errorCode); |
| 649 failWithException(new NetworkExceptionImpl( | 631 exception = new NetworkExceptionImpl( |
| 650 "Exception in CronetUrlRequest: " + errorString, javaError,
nativeError)); | 632 "Exception in CronetUrlRequest: " + errorString, javaError,
nativeError); |
| 651 } | 633 } |
| 634 setIsDone(exception, RequestFinishedInfo.FAILED); |
| 635 // onDestroyed() will propagate mException to callback. |
| 652 } | 636 } |
| 653 | 637 |
| 654 /** | 638 /** |
| 655 * Called when request is canceled, no callbacks will be called afterwards. | 639 * Called when request is canceled, no callbacks will be called afterwards. |
| 656 */ | 640 */ |
| 657 @SuppressWarnings("unused") | 641 @SuppressWarnings("unused") |
| 658 @CalledByNative | 642 @CalledByNative |
| 659 private void onCanceled() { | 643 private void onCanceled() { |
| 660 mFinishedReason = RequestFinishedInfo.CANCELED; | 644 setIsDone(null, RequestFinishedInfo.CANCELED); |
| 661 Runnable task = new Runnable() { | 645 Runnable task = new Runnable() { |
| 662 @Override | 646 @Override |
| 663 public void run() { | 647 public void run() { |
| 664 try { | 648 try { |
| 665 mCallback.onCanceled(CronetUrlRequest.this, mResponseInfo); | 649 mCallback.onCanceled(CronetUrlRequest.this, mResponseInfo); |
| 666 } catch (Exception e) { | 650 } catch (Exception e) { |
| 667 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onCance
led method", e); | 651 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onCance
led method", e); |
| 668 } | 652 } |
| 669 } | 653 } |
| 670 }; | 654 }; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 691 /** | 675 /** |
| 692 * Called by the native code to report metrics. | 676 * Called by the native code to report metrics. |
| 693 */ | 677 */ |
| 694 @SuppressWarnings("unused") | 678 @SuppressWarnings("unused") |
| 695 @CalledByNative | 679 @CalledByNative |
| 696 private void onMetricsCollected(long requestStartMs, long dnsStartMs, long d
nsEndMs, | 680 private void onMetricsCollected(long requestStartMs, long dnsStartMs, long d
nsEndMs, |
| 697 long connectStartMs, long connectEndMs, long sslStartMs, long sslEnd
Ms, | 681 long connectStartMs, long connectEndMs, long sslStartMs, long sslEnd
Ms, |
| 698 long sendingStartMs, long sendingEndMs, long pushStartMs, long pushE
ndMs, | 682 long sendingStartMs, long sendingEndMs, long pushStartMs, long pushE
ndMs, |
| 699 long responseStartMs, long requestEndMs, boolean socketReused, long
sentByteCount, | 683 long responseStartMs, long requestEndMs, boolean socketReused, long
sentByteCount, |
| 700 long receivedByteCount) { | 684 long receivedByteCount) { |
| 701 synchronized (mUrlRequestAdapterLock) { | 685 if (mMetricsCollected) { |
| 702 if (mMetrics != null) { | 686 throw new IllegalStateException("Metrics collection should only happ
en once."); |
| 703 throw new IllegalStateException("Metrics collection should only
happen once."); | |
| 704 } | |
| 705 mMetrics = new CronetMetrics(requestStartMs, dnsStartMs, dnsEndMs, c
onnectStartMs, | |
| 706 connectEndMs, sslStartMs, sslEndMs, sendingStartMs, sendingE
ndMs, pushStartMs, | |
| 707 pushEndMs, responseStartMs, requestEndMs, socketReused, sent
ByteCount, | |
| 708 receivedByteCount); | |
| 709 } | 687 } |
| 710 mRequestContext.reportFinished(getRequestFinishedInfo()); | 688 mMetricsCollected = true; |
| 689 CronetMetrics metrics = new CronetMetrics(requestStartMs, dnsStartMs, dn
sEndMs, |
| 690 connectStartMs, connectEndMs, sslStartMs, sslEndMs, sendingStart
Ms, sendingEndMs, |
| 691 pushStartMs, pushEndMs, responseStartMs, requestEndMs, socketReu
sed, sentByteCount, |
| 692 receivedByteCount); |
| 693 mRequestContext.reportFinished(new RequestFinishedInfoImpl(mInitialUrl,
mRequestAnnotations, |
| 694 metrics, mFinishedReason, mResponseInfo, mException)); |
| 711 } | 695 } |
| 712 | 696 |
| 713 private RequestFinishedInfo getRequestFinishedInfo() { | 697 /** |
| 714 return new RequestFinishedInfoImpl(mInitialUrl, mRequestAnnotations, mMe
trics, | 698 * Called when the native adapter is destroyed. |
| 715 mFinishedReason, mResponseInfo, mException); | 699 */ |
| 700 @SuppressWarnings("unused") |
| 701 @CalledByNative |
| 702 private void onDestroyed() { |
| 703 synchronized (mUrlRequestAdapterLock) { |
| 704 if (mOnDestroyedCallbackForTesting != null) { |
| 705 mOnDestroyedCallbackForTesting.run(); |
| 706 } |
| 707 if (mException == null) { |
| 708 return; |
| 709 } |
| 710 } |
| 711 Runnable task = new Runnable() { |
| 712 @Override |
| 713 public void run() { |
| 714 try { |
| 715 mCallback.onFailed(CronetUrlRequest.this, mResponseInfo, mEx
ception); |
| 716 } catch (Exception e) { |
| 717 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onFaile
d method", e); |
| 718 } |
| 719 } |
| 720 }; |
| 721 try { |
| 722 mExecutor.execute(task); |
| 723 } catch (RejectedExecutionException e) { |
| 724 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex
ecutor", e); |
| 725 } |
| 716 } | 726 } |
| 717 | 727 |
| 718 /** Enforces prohibition of direct execution. */ | 728 /** Enforces prohibition of direct execution. */ |
| 719 void checkCallingThread() { | 729 void checkCallingThread() { |
| 720 if (!mAllowDirectExecutor && mRequestContext.isNetworkThread(Thread.curr
entThread())) { | 730 if (!mAllowDirectExecutor && mRequestContext.isNetworkThread(Thread.curr
entThread())) { |
| 721 throw new InlineExecutionProhibitedException(); | 731 throw new InlineExecutionProhibitedException(); |
| 722 } | 732 } |
| 723 } | 733 } |
| 724 | 734 |
| 725 private int mapUrlRequestErrorToApiErrorCode(int errorCode) { | 735 private int mapUrlRequestErrorToApiErrorCode(int errorCode) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 768 private native void nativeStart(long nativePtr); | 778 private native void nativeStart(long nativePtr); |
| 769 | 779 |
| 770 @NativeClassQualifiedName("CronetURLRequestAdapter") | 780 @NativeClassQualifiedName("CronetURLRequestAdapter") |
| 771 private native void nativeFollowDeferredRedirect(long nativePtr); | 781 private native void nativeFollowDeferredRedirect(long nativePtr); |
| 772 | 782 |
| 773 @NativeClassQualifiedName("CronetURLRequestAdapter") | 783 @NativeClassQualifiedName("CronetURLRequestAdapter") |
| 774 private native boolean nativeReadData( | 784 private native boolean nativeReadData( |
| 775 long nativePtr, ByteBuffer byteBuffer, int position, int capacity); | 785 long nativePtr, ByteBuffer byteBuffer, int position, int capacity); |
| 776 | 786 |
| 777 @NativeClassQualifiedName("CronetURLRequestAdapter") | 787 @NativeClassQualifiedName("CronetURLRequestAdapter") |
| 778 private native void nativeDestroy(long nativePtr, boolean sendOnCanceled); | 788 private native void nativeCancel(long nativePtr); |
| 789 |
| 790 @NativeClassQualifiedName("CronetURLRequestAdapter") |
| 791 private native void nativeDestroy(long nativePtr); |
| 779 | 792 |
| 780 @NativeClassQualifiedName("CronetURLRequestAdapter") | 793 @NativeClassQualifiedName("CronetURLRequestAdapter") |
| 781 private native void nativeGetStatus( | 794 private native void nativeGetStatus( |
| 782 long nativePtr, VersionSafeCallbacks.UrlRequestStatusListener listen
er); | 795 long nativePtr, VersionSafeCallbacks.UrlRequestStatusListener listen
er); |
| 783 } | 796 } |
| OLD | NEW |