Chromium Code Reviews| 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 // These three should only be updated once with mUrlRequestAdapterLock held. They are read on | |
| 90 // URLRequest.Callback executor's and RequestFinishedListener's thread after the last update. | |
|
mgersh
2017/05/02 18:21:12
nits: UrlRequest, RequestFinishedInfo.Listener.
T
xunjieli
2017/05/02 23:30:23
Done.
| |
| 91 @RequestFinishedInfoImpl.FinishedReason | |
| 92 private int mFinishedReason; | |
| 93 private CronetException mException; | |
| 94 private CronetMetrics mMetrics; | |
| 95 | |
| 94 /* | 96 /* |
| 95 * Listener callback is repeatedly invoked when each read is completed, so i t | 97 * Listener callback is repeatedly invoked when each read is completed, so i t |
| 96 * is cached as a member variable. | 98 * is cached as a member variable. |
| 97 */ | 99 */ |
| 98 private OnReadCompletedRunnable mOnReadCompletedTask; | 100 private OnReadCompletedRunnable mOnReadCompletedTask; |
| 99 | 101 |
| 102 @GuardedBy("mUrlRequestAdapterLock") | |
| 100 private Runnable mOnDestroyedCallbackForTesting; | 103 private Runnable mOnDestroyedCallbackForTesting; |
| 101 | 104 |
| 102 private static final class HeadersList extends ArrayList<Map.Entry<String, S tring>> {} | 105 private static final class HeadersList extends ArrayList<Map.Entry<String, S tring>> {} |
| 103 | 106 |
| 104 private final class OnReadCompletedRunnable implements Runnable { | 107 private final class OnReadCompletedRunnable implements Runnable { |
| 105 // Buffer passed back from current invocation of onReadCompleted. | 108 // Buffer passed back from current invocation of onReadCompleted. |
| 106 ByteBuffer mByteBuffer; | 109 ByteBuffer mByteBuffer; |
| 107 | 110 |
| 108 @Override | 111 @Override |
| 109 public void run() { | 112 public void run() { |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 227 return; | 230 return; |
| 228 } | 231 } |
| 229 mUploadDataStream.attachNativeAdapterToRequest(m UrlRequestAdapter); | 232 mUploadDataStream.attachNativeAdapterToRequest(m UrlRequestAdapter); |
| 230 startInternalLocked(); | 233 startInternalLocked(); |
| 231 } | 234 } |
| 232 } | 235 } |
| 233 }); | 236 }); |
| 234 return; | 237 return; |
| 235 } | 238 } |
| 236 } catch (RuntimeException e) { | 239 } catch (RuntimeException e) { |
| 237 // If there's an exception, cleanup and then throw the | 240 // If there's an exception, cleanup and then throw the exception to the caller. |
| 238 // exception to the caller. | 241 // start() is synchronized so we do not acquire mUrlRequestAdapt erLock here. |
| 239 destroyRequestAdapter(false); | 242 destroyRequestAdapterLocked(RequestFinishedInfo.FAILED); |
| 240 throw e; | 243 throw e; |
| 241 } | 244 } |
| 242 mStarted = true; | 245 mStarted = true; |
| 243 startInternalLocked(); | 246 startInternalLocked(); |
| 244 } | 247 } |
| 245 } | 248 } |
| 246 | 249 |
| 247 /* | 250 /* |
| 248 * Starts fully configured request. Could execute on UploadDataProvider exec utor. | 251 * 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. | 252 * 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 } | 294 } |
| 292 } | 295 } |
| 293 } | 296 } |
| 294 | 297 |
| 295 @Override | 298 @Override |
| 296 public void cancel() { | 299 public void cancel() { |
| 297 synchronized (mUrlRequestAdapterLock) { | 300 synchronized (mUrlRequestAdapterLock) { |
| 298 if (isDoneLocked() || !mStarted) { | 301 if (isDoneLocked() || !mStarted) { |
| 299 return; | 302 return; |
| 300 } | 303 } |
| 301 destroyRequestAdapter(true); | 304 destroyRequestAdapterLocked(RequestFinishedInfo.CANCELED); |
| 302 } | 305 } |
| 303 } | 306 } |
| 304 | 307 |
| 305 @Override | 308 @Override |
| 306 public boolean isDone() { | 309 public boolean isDone() { |
| 307 synchronized (mUrlRequestAdapterLock) { | 310 synchronized (mUrlRequestAdapterLock) { |
| 308 return isDoneLocked(); | 311 return isDoneLocked(); |
| 309 } | 312 } |
| 310 } | 313 } |
| 311 | 314 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 328 @Override | 331 @Override |
| 329 public void run() { | 332 public void run() { |
| 330 listener.onStatus(UrlRequest.Status.INVALID); | 333 listener.onStatus(UrlRequest.Status.INVALID); |
| 331 } | 334 } |
| 332 }; | 335 }; |
| 333 postTaskToExecutor(task); | 336 postTaskToExecutor(task); |
| 334 } | 337 } |
| 335 | 338 |
| 336 @VisibleForTesting | 339 @VisibleForTesting |
| 337 public void setOnDestroyedCallbackForTesting(Runnable onDestroyedCallbackFor Testing) { | 340 public void setOnDestroyedCallbackForTesting(Runnable onDestroyedCallbackFor Testing) { |
| 338 mOnDestroyedCallbackForTesting = onDestroyedCallbackForTesting; | 341 synchronized (mUrlRequestAdapterLock) { |
| 342 mOnDestroyedCallbackForTesting = onDestroyedCallbackForTesting; | |
| 343 } | |
| 339 } | 344 } |
| 340 | 345 |
| 341 @VisibleForTesting | 346 @VisibleForTesting |
| 342 public void setOnDestroyedUploadCallbackForTesting( | 347 public void setOnDestroyedUploadCallbackForTesting( |
| 343 Runnable onDestroyedUploadCallbackForTesting) { | 348 Runnable onDestroyedUploadCallbackForTesting) { |
| 344 mUploadDataStream.setOnDestroyedCallbackForTesting(onDestroyedUploadCall backForTesting); | 349 mUploadDataStream.setOnDestroyedCallbackForTesting(onDestroyedUploadCall backForTesting); |
| 345 } | 350 } |
| 346 | 351 |
| 347 @VisibleForTesting | 352 @VisibleForTesting |
| 348 public long getUrlRequestAdapterForTesting() { | 353 public long getUrlRequestAdapterForTesting() { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 } | 408 } |
| 404 | 409 |
| 405 private void checkNotStarted() { | 410 private void checkNotStarted() { |
| 406 synchronized (mUrlRequestAdapterLock) { | 411 synchronized (mUrlRequestAdapterLock) { |
| 407 if (mStarted || isDoneLocked()) { | 412 if (mStarted || isDoneLocked()) { |
| 408 throw new IllegalStateException("Request is already started."); | 413 throw new IllegalStateException("Request is already started."); |
| 409 } | 414 } |
| 410 } | 415 } |
| 411 } | 416 } |
| 412 | 417 |
| 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 /** | 418 /** |
| 419 * Helper method to set final status of CronetUrlRequest and clean up the | |
| 420 * native request adapter. | |
| 421 */ | |
| 422 @GuardedBy("mUrlRequestAdapterLock") | |
| 423 private void destroyRequestAdapterLocked( | |
| 424 @RequestFinishedInfoImpl.FinishedReason int finishedReason) { | |
| 425 assert mException == null || finishedReason == RequestFinishedInfo.FAILE D; | |
| 426 mFinishedReason = finishedReason; | |
| 427 if (mUrlRequestAdapter == 0) { | |
| 428 return; | |
| 429 } | |
| 430 mRequestContext.onRequestDestroyed(); | |
| 431 // Posts a task to destroy the native adapter. | |
| 432 nativeDestroy(mUrlRequestAdapter, finishedReason == RequestFinishedInfo. CANCELED); | |
| 433 mUrlRequestAdapter = 0; | |
| 434 } | |
| 435 | |
| 436 /** | |
| 428 * If callback method throws an exception, request gets canceled | 437 * If callback method throws an exception, request gets canceled |
| 429 * and exception is reported via onFailed listener callback. | 438 * and exception is reported via onFailed listener callback. |
| 430 * Only called on the Executor. | 439 * Only called on the Executor. |
| 431 */ | 440 */ |
| 432 private void onCallbackException(Exception e) { | 441 private void onCallbackException(Exception e) { |
| 433 CallbackException requestError = | 442 CallbackException requestError = |
| 434 new CallbackExceptionImpl("Exception received from UrlRequest.Ca llback", e); | 443 new CallbackExceptionImpl("Exception received from UrlRequest.Ca llback", e); |
| 435 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in CalledByNative meth od", e); | 444 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in CalledByNative meth od", e); |
| 436 failWithException(requestError); | 445 failWithException(requestError); |
| 437 } | 446 } |
| 438 | 447 |
| 439 /** | 448 /** |
| 440 * Called when UploadDataProvider encounters an error. | 449 * Called when UploadDataProvider encounters an error. |
| 441 */ | 450 */ |
| 442 void onUploadException(Throwable e) { | 451 void onUploadException(Throwable e) { |
| 443 CallbackException uploadError = | 452 CallbackException uploadError = |
| 444 new CallbackExceptionImpl("Exception received from UploadDataPro vider", e); | 453 new CallbackExceptionImpl("Exception received from UploadDataPro vider", e); |
| 445 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in upload method", e); | 454 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in upload method", e); |
| 446 failWithException(uploadError); | 455 failWithException(uploadError); |
| 447 } | 456 } |
| 448 | 457 |
| 449 /** | 458 /** |
| 450 * Fails the request with an exception. Can be called on any thread. | 459 * Fails the request with an exception on any thread. |
| 451 */ | 460 */ |
| 452 private void failWithException(final CronetException exception) { | 461 private void failWithException(final CronetException exception) { |
| 453 mException = exception; | |
| 454 synchronized (mUrlRequestAdapterLock) { | 462 synchronized (mUrlRequestAdapterLock) { |
| 455 if (isDoneLocked()) { | 463 if (isDoneLocked()) { |
| 456 return; | 464 return; |
| 457 } | 465 } |
| 458 destroyRequestAdapter(false); | 466 assert mException == null; |
| 467 mException = exception; | |
| 468 destroyRequestAdapterLocked(RequestFinishedInfo.FAILED); | |
| 459 } | 469 } |
| 460 Runnable task = new Runnable() { | 470 // The onFailed callback will be invoked from onNativeAdapterDestroyed() to ensure metrics |
| 461 @Override | 471 // collection |
|
mgersh
2017/05/02 18:21:13
nit: missing period at the end
xunjieli
2017/05/02 23:30:23
Done.
| |
| 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 } | |
| 475 } | 472 } |
| 476 | 473 |
| 477 //////////////////////////////////////////////// | 474 //////////////////////////////////////////////// |
| 478 // Private methods called by the native code. | 475 // Private methods called by the native code. |
| 479 // Always called on network thread. | 476 // Always called on network thread. |
| 480 //////////////////////////////////////////////// | 477 //////////////////////////////////////////////// |
| 481 | 478 |
| 482 /** | 479 /** |
| 483 * Called before following redirects. The redirect will only be followed if | 480 * Called before following redirects. The redirect will only be followed if |
| 484 * {@link #followRedirect()} is called. If the redirect response has a body, it will be ignored. | 481 * {@link #followRedirect()} is called. If the redirect response has a body, it will be ignored. |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 593 | 590 |
| 594 /** | 591 /** |
| 595 * Called when request is completed successfully, no callbacks will be | 592 * Called when request is completed successfully, no callbacks will be |
| 596 * called afterwards. | 593 * called afterwards. |
| 597 * | 594 * |
| 598 * @param receivedByteCount number of bytes received. | 595 * @param receivedByteCount number of bytes received. |
| 599 */ | 596 */ |
| 600 @SuppressWarnings("unused") | 597 @SuppressWarnings("unused") |
| 601 @CalledByNative | 598 @CalledByNative |
| 602 private void onSucceeded(long receivedByteCount) { | 599 private void onSucceeded(long receivedByteCount) { |
| 603 mFinishedReason = RequestFinishedInfo.SUCCEEDED; | |
| 604 mResponseInfo.setReceivedByteCount(mReceivedByteCountFromRedirects + rec eivedByteCount); | 600 mResponseInfo.setReceivedByteCount(mReceivedByteCountFromRedirects + rec eivedByteCount); |
| 605 Runnable task = new Runnable() { | 601 Runnable task = new Runnable() { |
| 606 @Override | 602 @Override |
| 607 public void run() { | 603 public void run() { |
| 608 synchronized (mUrlRequestAdapterLock) { | 604 synchronized (mUrlRequestAdapterLock) { |
| 609 if (isDoneLocked()) { | 605 if (isDoneLocked()) { |
| 610 return; | 606 return; |
| 611 } | 607 } |
| 612 // Destroy adapter first, so request context could be shut | 608 // Destroy adapter first, so request context could be shut |
| 613 // down from the listener. | 609 // down from the listener. |
| 614 destroyRequestAdapter(false); | 610 destroyRequestAdapterLocked(RequestFinishedInfo.SUCCEEDED); |
| 615 } | 611 } |
| 616 try { | 612 try { |
| 617 mCallback.onSucceeded(CronetUrlRequest.this, mResponseInfo); | 613 mCallback.onSucceeded(CronetUrlRequest.this, mResponseInfo); |
| 614 maybeReportMetrics(); | |
| 618 } catch (Exception e) { | 615 } catch (Exception e) { |
| 619 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onCompl ete method", e); | 616 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onSucce eded method", e); |
| 620 } | 617 } |
| 621 } | 618 } |
| 622 }; | 619 }; |
| 623 postTaskToExecutor(task); | 620 postTaskToExecutor(task); |
| 624 } | 621 } |
| 625 | 622 |
| 626 /** | 623 /** |
| 627 * Called when error has occured, no callbacks will be called afterwards. | 624 * Called when error has occured, no callbacks will be called afterwards. |
| 628 * | 625 * |
| 629 * @param errorCode Error code represented by {@code UrlRequestError} that s hould be mapped | 626 * @param errorCode Error code represented by {@code UrlRequestError} that s hould be mapped |
| 630 * to one of {@link NetworkException#ERROR_HOSTNAME_NOT_RES OLVED | 627 * to one of {@link NetworkException#ERROR_HOSTNAME_NOT_RES OLVED |
| 631 * NetworkException.ERROR_*}. | 628 * NetworkException.ERROR_*}. |
| 632 * @param nativeError native net error code. | 629 * @param nativeError native net error code. |
| 633 * @param errorString textual representation of the error code. | 630 * @param errorString textual representation of the error code. |
| 634 * @param receivedByteCount number of bytes received. | 631 * @param receivedByteCount number of bytes received. |
| 635 */ | 632 */ |
| 636 @SuppressWarnings("unused") | 633 @SuppressWarnings("unused") |
| 637 @CalledByNative | 634 @CalledByNative |
| 638 private void onError(int errorCode, int nativeError, int nativeQuicError, St ring errorString, | 635 private void onError(int errorCode, int nativeError, int nativeQuicError, St ring errorString, |
| 639 long receivedByteCount) { | 636 long receivedByteCount) { |
| 640 mFinishedReason = RequestFinishedInfo.FAILED; | |
| 641 if (mResponseInfo != null) { | 637 if (mResponseInfo != null) { |
| 642 mResponseInfo.setReceivedByteCount(mReceivedByteCountFromRedirects + receivedByteCount); | 638 mResponseInfo.setReceivedByteCount(mReceivedByteCountFromRedirects + receivedByteCount); |
| 643 } | 639 } |
| 644 if (errorCode == NetworkException.ERROR_QUIC_PROTOCOL_FAILED) { | 640 if (errorCode == NetworkException.ERROR_QUIC_PROTOCOL_FAILED) { |
| 645 failWithException(new QuicExceptionImpl( | 641 failWithException(new QuicExceptionImpl( |
| 646 "Exception in CronetUrlRequest: " + errorString, nativeError , nativeQuicError)); | 642 "Exception in CronetUrlRequest: " + errorString, nativeError , nativeQuicError)); |
| 647 } else { | 643 } else { |
| 648 int javaError = mapUrlRequestErrorToApiErrorCode(errorCode); | 644 int javaError = mapUrlRequestErrorToApiErrorCode(errorCode); |
| 649 failWithException(new NetworkExceptionImpl( | 645 failWithException(new NetworkExceptionImpl( |
| 650 "Exception in CronetUrlRequest: " + errorString, javaError, nativeError)); | 646 "Exception in CronetUrlRequest: " + errorString, javaError, nativeError)); |
| 651 } | 647 } |
| 652 } | 648 } |
| 653 | 649 |
| 654 /** | 650 /** |
| 655 * Called when request is canceled, no callbacks will be called afterwards. | 651 * Called when request is canceled, no callbacks will be called afterwards. |
| 656 */ | 652 */ |
| 657 @SuppressWarnings("unused") | 653 @SuppressWarnings("unused") |
| 658 @CalledByNative | 654 @CalledByNative |
| 659 private void onCanceled() { | 655 private void onCanceled() { |
| 660 mFinishedReason = RequestFinishedInfo.CANCELED; | |
| 661 Runnable task = new Runnable() { | 656 Runnable task = new Runnable() { |
| 662 @Override | 657 @Override |
| 663 public void run() { | 658 public void run() { |
| 664 try { | 659 try { |
| 665 mCallback.onCanceled(CronetUrlRequest.this, mResponseInfo); | 660 mCallback.onCanceled(CronetUrlRequest.this, mResponseInfo); |
| 661 maybeReportMetrics(); | |
| 666 } catch (Exception e) { | 662 } catch (Exception e) { |
| 667 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onCance led method", e); | 663 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onCance led method", e); |
| 668 } | 664 } |
| 669 } | 665 } |
| 670 }; | 666 }; |
| 671 postTaskToExecutor(task); | 667 postTaskToExecutor(task); |
| 672 } | 668 } |
| 673 | 669 |
| 674 /** | 670 /** |
| 675 * Called by the native code when request status is fetched from the | 671 * Called by the native code when request status is fetched from the |
| 676 * native stack. | 672 * native stack. |
| 677 */ | 673 */ |
| 678 @SuppressWarnings("unused") | 674 @SuppressWarnings("unused") |
| 679 @CalledByNative | 675 @CalledByNative |
| 680 private void onStatus( | 676 private void onStatus( |
| 681 final VersionSafeCallbacks.UrlRequestStatusListener listener, final int loadState) { | 677 final VersionSafeCallbacks.UrlRequestStatusListener listener, final int loadState) { |
| 682 Runnable task = new Runnable() { | 678 Runnable task = new Runnable() { |
| 683 @Override | 679 @Override |
| 684 public void run() { | 680 public void run() { |
| 685 listener.onStatus(convertLoadState(loadState)); | 681 listener.onStatus(convertLoadState(loadState)); |
| 686 } | 682 } |
| 687 }; | 683 }; |
| 688 postTaskToExecutor(task); | 684 postTaskToExecutor(task); |
| 689 } | 685 } |
| 690 | 686 |
| 691 /** | 687 /** |
| 692 * Called by the native code to report metrics. | 688 * Called by the native code on the network thread to report metrics. Happen s before |
| 689 * onSucceeded, onError and onCanceled. | |
| 693 */ | 690 */ |
| 694 @SuppressWarnings("unused") | 691 @SuppressWarnings("unused") |
| 695 @CalledByNative | 692 @CalledByNative |
| 696 private void onMetricsCollected(long requestStartMs, long dnsStartMs, long d nsEndMs, | 693 private void onMetricsCollected(long requestStartMs, long dnsStartMs, long d nsEndMs, |
| 697 long connectStartMs, long connectEndMs, long sslStartMs, long sslEnd Ms, | 694 long connectStartMs, long connectEndMs, long sslStartMs, long sslEnd Ms, |
| 698 long sendingStartMs, long sendingEndMs, long pushStartMs, long pushE ndMs, | 695 long sendingStartMs, long sendingEndMs, long pushStartMs, long pushE ndMs, |
| 699 long responseStartMs, long requestEndMs, boolean socketReused, long sentByteCount, | 696 long responseStartMs, long requestEndMs, boolean socketReused, long sentByteCount, |
| 700 long receivedByteCount) { | 697 long receivedByteCount) { |
| 701 synchronized (mUrlRequestAdapterLock) { | 698 synchronized (mUrlRequestAdapterLock) { |
| 702 if (mMetrics != null) { | 699 if (mMetrics != null) { |
| 703 throw new IllegalStateException("Metrics collection should only happen once."); | 700 throw new IllegalStateException("Metrics collection should only happen once."); |
| 704 } | 701 } |
| 705 mMetrics = new CronetMetrics(requestStartMs, dnsStartMs, dnsEndMs, c onnectStartMs, | 702 mMetrics = new CronetMetrics(requestStartMs, dnsStartMs, dnsEndMs, c onnectStartMs, |
| 706 connectEndMs, sslStartMs, sslEndMs, sendingStartMs, sendingE ndMs, pushStartMs, | 703 connectEndMs, sslStartMs, sslEndMs, sendingStartMs, sendingE ndMs, pushStartMs, |
| 707 pushEndMs, responseStartMs, requestEndMs, socketReused, sent ByteCount, | 704 pushEndMs, responseStartMs, requestEndMs, socketReused, sent ByteCount, |
| 708 receivedByteCount); | 705 receivedByteCount); |
| 709 } | 706 } |
| 710 mRequestContext.reportFinished(getRequestFinishedInfo()); | 707 // Metrics are reported to RequestFinishedListener when the final UrlReq uest.Callback has |
| 708 // been invoked. | |
| 711 } | 709 } |
| 712 | 710 |
| 713 private RequestFinishedInfo getRequestFinishedInfo() { | 711 /** |
| 714 return new RequestFinishedInfoImpl(mInitialUrl, mRequestAnnotations, mMe trics, | 712 * Called when the native adapter is destroyed. |
| 715 mFinishedReason, mResponseInfo, mException); | 713 */ |
| 714 @SuppressWarnings("unused") | |
| 715 @CalledByNative | |
| 716 private void onNativeAdapterDestroyed() { | |
| 717 synchronized (mUrlRequestAdapterLock) { | |
| 718 if (mOnDestroyedCallbackForTesting != null) { | |
| 719 mOnDestroyedCallbackForTesting.run(); | |
| 720 } | |
| 721 // mException is set when an error is encountered (in native code vi a onError or in | |
| 722 // Java code). If mException is not null, notify the mCallback and r eport metrics. | |
| 723 if (mException == null) { | |
| 724 return; | |
| 725 } | |
| 726 } | |
| 727 Runnable task = new Runnable() { | |
| 728 @Override | |
| 729 public void run() { | |
| 730 try { | |
| 731 mCallback.onFailed(CronetUrlRequest.this, mResponseInfo, mEx ception); | |
| 732 maybeReportMetrics(); | |
| 733 } catch (Exception e) { | |
| 734 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onFaile d method", e); | |
| 735 } | |
| 736 } | |
| 737 }; | |
| 738 try { | |
| 739 mExecutor.execute(task); | |
| 740 } catch (RejectedExecutionException e) { | |
| 741 Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to ex ecutor", e); | |
| 742 } | |
| 716 } | 743 } |
| 717 | 744 |
| 718 /** Enforces prohibition of direct execution. */ | 745 /** Enforces prohibition of direct execution. */ |
| 719 void checkCallingThread() { | 746 void checkCallingThread() { |
| 720 if (!mAllowDirectExecutor && mRequestContext.isNetworkThread(Thread.curr entThread())) { | 747 if (!mAllowDirectExecutor && mRequestContext.isNetworkThread(Thread.curr entThread())) { |
| 721 throw new InlineExecutionProhibitedException(); | 748 throw new InlineExecutionProhibitedException(); |
| 722 } | 749 } |
| 723 } | 750 } |
| 724 | 751 |
| 725 private int mapUrlRequestErrorToApiErrorCode(int errorCode) { | 752 private int mapUrlRequestErrorToApiErrorCode(int errorCode) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 745 case UrlRequestError.QUIC_PROTOCOL_FAILED: | 772 case UrlRequestError.QUIC_PROTOCOL_FAILED: |
| 746 return NetworkException.ERROR_QUIC_PROTOCOL_FAILED; | 773 return NetworkException.ERROR_QUIC_PROTOCOL_FAILED; |
| 747 case UrlRequestError.OTHER: | 774 case UrlRequestError.OTHER: |
| 748 return NetworkException.ERROR_OTHER; | 775 return NetworkException.ERROR_OTHER; |
| 749 default: | 776 default: |
| 750 Log.e(CronetUrlRequestContext.LOG_TAG, "Unknown error code: " + errorCode); | 777 Log.e(CronetUrlRequestContext.LOG_TAG, "Unknown error code: " + errorCode); |
| 751 return errorCode; | 778 return errorCode; |
| 752 } | 779 } |
| 753 } | 780 } |
| 754 | 781 |
| 782 // Maybe report metrics. This method should only be called on Callback's exe cutor thread and | |
| 783 // after Callback's onSucceeded, onFailed and onCanceled. | |
| 784 private void maybeReportMetrics() { | |
| 785 if (mMetrics != null) { | |
| 786 mRequestContext.reportFinished(new RequestFinishedInfoImpl(mInitialU rl, | |
| 787 mRequestAnnotations, mMetrics, mFinishedReason, mResponseInf o, mException)); | |
| 788 } | |
| 789 } | |
| 790 | |
| 755 // Native methods are implemented in cronet_url_request_adapter.cc. | 791 // Native methods are implemented in cronet_url_request_adapter.cc. |
| 756 | 792 |
| 757 private native long nativeCreateRequestAdapter(long urlRequestContextAdapter , String url, | 793 private native long nativeCreateRequestAdapter(long urlRequestContextAdapter , String url, |
| 758 int priority, boolean disableCache, boolean disableConnectionMigrati on, | 794 int priority, boolean disableCache, boolean disableConnectionMigrati on, |
| 759 boolean enableMetrics); | 795 boolean enableMetrics); |
| 760 | 796 |
| 761 @NativeClassQualifiedName("CronetURLRequestAdapter") | 797 @NativeClassQualifiedName("CronetURLRequestAdapter") |
| 762 private native boolean nativeSetHttpMethod(long nativePtr, String method); | 798 private native boolean nativeSetHttpMethod(long nativePtr, String method); |
| 763 | 799 |
| 764 @NativeClassQualifiedName("CronetURLRequestAdapter") | 800 @NativeClassQualifiedName("CronetURLRequestAdapter") |
| 765 private native boolean nativeAddRequestHeader(long nativePtr, String name, S tring value); | 801 private native boolean nativeAddRequestHeader(long nativePtr, String name, S tring value); |
| 766 | 802 |
| 767 @NativeClassQualifiedName("CronetURLRequestAdapter") | 803 @NativeClassQualifiedName("CronetURLRequestAdapter") |
| 768 private native void nativeStart(long nativePtr); | 804 private native void nativeStart(long nativePtr); |
| 769 | 805 |
| 770 @NativeClassQualifiedName("CronetURLRequestAdapter") | 806 @NativeClassQualifiedName("CronetURLRequestAdapter") |
| 771 private native void nativeFollowDeferredRedirect(long nativePtr); | 807 private native void nativeFollowDeferredRedirect(long nativePtr); |
| 772 | 808 |
| 773 @NativeClassQualifiedName("CronetURLRequestAdapter") | 809 @NativeClassQualifiedName("CronetURLRequestAdapter") |
| 774 private native boolean nativeReadData( | 810 private native boolean nativeReadData( |
| 775 long nativePtr, ByteBuffer byteBuffer, int position, int capacity); | 811 long nativePtr, ByteBuffer byteBuffer, int position, int capacity); |
| 776 | 812 |
| 777 @NativeClassQualifiedName("CronetURLRequestAdapter") | 813 @NativeClassQualifiedName("CronetURLRequestAdapter") |
| 778 private native void nativeDestroy(long nativePtr, boolean sendOnCanceled); | 814 private native void nativeDestroy(long nativePtr, boolean sendOnCanceled); |
| 779 | 815 |
| 780 @NativeClassQualifiedName("CronetURLRequestAdapter") | 816 @NativeClassQualifiedName("CronetURLRequestAdapter") |
| 781 private native void nativeGetStatus( | 817 private native void nativeGetStatus( |
| 782 long nativePtr, VersionSafeCallbacks.UrlRequestStatusListener listen er); | 818 long nativePtr, VersionSafeCallbacks.UrlRequestStatusListener listen er); |
| 783 } | 819 } |
| OLD | NEW |