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

Side by Side Diff: components/cronet/android/api/src/org/chromium/net/JavaUrlRequest.java

Issue 2302253003: Improve error handling in JavaUrlRequest (Closed)
Patch Set: Remove errant comment change 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
« no previous file with comments | « no previous file | components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestTest.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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; 5 package org.chromium.net;
6 6
7 import android.annotation.TargetApi; 7 import android.annotation.TargetApi;
8 import android.net.TrafficStats; 8 import android.net.TrafficStats;
9 import android.os.Build; 9 import android.os.Build;
10 import android.util.Log; 10 import android.util.Log;
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 this.mUrlConnection = urlConnection; 283 this.mUrlConnection = urlConnection;
284 this.mUploadProvider = provider; 284 this.mUploadProvider = provider;
285 } 285 }
286 286
287 @Override 287 @Override
288 public void onReadSucceeded(final boolean finalChunk) { 288 public void onReadSucceeded(final boolean finalChunk) {
289 if (!mSinkState.compareAndSet(SinkState.AWAITING_READ_RESULT, SinkSt ate.UPLOADING)) { 289 if (!mSinkState.compareAndSet(SinkState.AWAITING_READ_RESULT, SinkSt ate.UPLOADING)) {
290 throw new IllegalStateException( 290 throw new IllegalStateException(
291 "Not expecting a read result, expecting: " + mSinkState. get()); 291 "Not expecting a read result, expecting: " + mSinkState. get());
292 } 292 }
293 mExecutor.execute(errorSetting(State.STARTED, new CheckedRunnable() { 293 mExecutor.execute(errorSetting(new CheckedRunnable() {
294 @Override 294 @Override
295 public void run() throws Exception { 295 public void run() throws Exception {
296 mBuffer.flip(); 296 mBuffer.flip();
297 if (mTotalBytes != -1 && mTotalBytes - mWrittenBytes < mBuff er.remaining()) { 297 if (mTotalBytes != -1 && mTotalBytes - mWrittenBytes < mBuff er.remaining()) {
298 enterUploadErrorState(new IllegalArgumentException(Strin g.format( 298 enterUploadErrorState(new IllegalArgumentException(Strin g.format(
299 "Read upload data length %d exceeds expected len gth %d", 299 "Read upload data length %d exceeds expected len gth %d",
300 mWrittenBytes + mBuffer.remaining(), mTotalBytes ))); 300 mWrittenBytes + mBuffer.remaining(), mTotalBytes )));
301 return; 301 return;
302 } 302 }
303 while (mBuffer.hasRemaining()) { 303 while (mBuffer.hasRemaining()) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 public void onReadError(Exception exception) { 337 public void onReadError(Exception exception) {
338 enterUploadErrorState(exception); 338 enterUploadErrorState(exception);
339 } 339 }
340 340
341 @Override 341 @Override
342 public void onRewindError(Exception exception) { 342 public void onRewindError(Exception exception) {
343 enterUploadErrorState(exception); 343 enterUploadErrorState(exception);
344 } 344 }
345 345
346 void startRead() { 346 void startRead() {
347 mExecutor.execute(errorSetting(State.STARTED, new CheckedRunnable() { 347 mExecutor.execute(errorSetting(new CheckedRunnable() {
348 @Override 348 @Override
349 public void run() throws Exception { 349 public void run() throws Exception {
350 if (mOutputChannel == null) { 350 if (mOutputChannel == null) {
351 mAdditionalStatusDetails = Status.CONNECTING; 351 mAdditionalStatusDetails = Status.CONNECTING;
352 mUrlConnection.connect(); 352 mUrlConnection.connect();
353 mAdditionalStatusDetails = Status.SENDING_REQUEST; 353 mAdditionalStatusDetails = Status.SENDING_REQUEST;
354 mOutputChannel = Channels.newChannel(mUrlConnection.getO utputStream()); 354 mOutputChannel = Channels.newChannel(mUrlConnection.getO utputStream());
355 } 355 }
356 mSinkState.set(SinkState.AWAITING_READ_RESULT); 356 mSinkState.set(SinkState.AWAITING_READ_RESULT);
357 executeOnUploadExecutor(new CheckedRunnable() { 357 executeOnUploadExecutor(new CheckedRunnable() {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 mAdditionalStatusDetails = Status.CONNECTING; 425 mAdditionalStatusDetails = Status.CONNECTING;
426 transitionStates(State.NOT_STARTED, State.STARTED, new Runnable() { 426 transitionStates(State.NOT_STARTED, State.STARTED, new Runnable() {
427 @Override 427 @Override
428 public void run() { 428 public void run() {
429 mUrlChain.add(mCurrentUrl); 429 mUrlChain.add(mCurrentUrl);
430 fireOpenConnection(); 430 fireOpenConnection();
431 } 431 }
432 }); 432 });
433 } 433 }
434 434
435 private void enterErrorState(State previousState, final UrlRequestException error) { 435 private void enterErrorState(final UrlRequestException error) {
436 if (mState.compareAndSet(previousState, State.ERROR)) { 436 if (setTerminalState(State.ERROR)) {
437 fireDisconnect(); 437 fireDisconnect();
438 fireCloseUploadDataProvider(); 438 fireCloseUploadDataProvider();
439 mCallbackAsync.onFailed(mUrlResponseInfo, error); 439 mCallbackAsync.onFailed(mUrlResponseInfo, error);
440 } 440 }
441 } 441 }
442 442
443 private boolean setTerminalState(State error) {
444 while (true) {
xunjieli 2016/09/02 21:05:01 I don't understand the need for a while-true loop.
Charles 2016/09/02 21:08:36 We're doing a compare-and-set continuously until w
xunjieli 2016/09/02 21:41:14 Acknowledged.
445 State oldState = mState.get();
446 switch (oldState) {
447 case NOT_STARTED:
448 throw new IllegalStateException("Can't enter error state bef ore start");
449 case ERROR: // fallthrough
450 case COMPLETE: // fallthrough
451 case CANCELLED:
452 return false; // Already in a terminal state
453 default: {
454 if (mState.compareAndSet(oldState, error)) {
455 return true;
456 }
457 }
458 }
459 }
460 }
461
443 /** Ends the request with an error, caused by an exception thrown from user code. */ 462 /** Ends the request with an error, caused by an exception thrown from user code. */
444 private void enterUserErrorState(State previousState, final Throwable error) { 463 private void enterUserErrorState(final Throwable error) {
445 enterErrorState(previousState, 464 enterErrorState(
446 new UrlRequestException("Exception received from UrlRequest.Call back", error)); 465 new UrlRequestException("Exception received from UrlRequest.Call back", error));
447 } 466 }
448 467
449 /** Ends the request with an error, caused by an exception thrown from user code. */ 468 /** Ends the request with an error, caused by an exception thrown from user code. */
450 private void enterUploadErrorState(final Throwable error) { 469 private void enterUploadErrorState(final Throwable error) {
451 enterErrorState(State.STARTED, 470 enterErrorState(
452 new UrlRequestException("Exception received from UploadDataProvi der", error)); 471 new UrlRequestException("Exception received from UploadDataProvi der", error));
453 } 472 }
454 473
455 private void enterCronetErrorState(State previousState, final Throwable erro r) { 474 private void enterCronetErrorState(final Throwable error) {
456 // TODO(clm) mapping from Java exception (UnknownHostException, for exam ple) to net error 475 // TODO(clm) mapping from Java exception (UnknownHostException, for exam ple) to net error
457 // code goes here. 476 // code goes here.
458 enterErrorState(previousState, new UrlRequestException("System error", e rror)); 477 enterErrorState(new UrlRequestException("System error", error));
459 } 478 }
460 479
461 /** 480 /**
462 * Atomically swaps from the expected state to a new state. If the swap fail s, and it's not 481 * Atomically swaps from the expected state to a new state. If the swap fail s, and it's not
463 * due to an earlier error or cancellation, throws an exception. 482 * due to an earlier error or cancellation, throws an exception.
464 * 483 *
465 * @param afterTransition Callback to run after transition completes success fully. 484 * @param afterTransition Callback to run after transition completes success fully.
466 */ 485 */
467 private void transitionStates(State expected, State newState, Runnable after Transition) { 486 private void transitionStates(State expected, State newState, Runnable after Transition) {
468 if (!mState.compareAndSet(expected, newState)) { 487 if (!mState.compareAndSet(expected, newState)) {
(...skipping 14 matching lines...) Expand all
483 public void run() { 502 public void run() {
484 mCurrentUrl = mPendingRedirectUrl; 503 mCurrentUrl = mPendingRedirectUrl;
485 mPendingRedirectUrl = null; 504 mPendingRedirectUrl = null;
486 fireOpenConnection(); 505 fireOpenConnection();
487 } 506 }
488 }); 507 });
489 } 508 }
490 509
491 private void fireGetHeaders() { 510 private void fireGetHeaders() {
492 mAdditionalStatusDetails = Status.WAITING_FOR_RESPONSE; 511 mAdditionalStatusDetails = Status.WAITING_FOR_RESPONSE;
493 mExecutor.execute(errorSetting(State.STARTED, new CheckedRunnable() { 512 mExecutor.execute(errorSetting(new CheckedRunnable() {
494 @Override 513 @Override
495 public void run() throws Exception { 514 public void run() throws Exception {
496 HttpURLConnection connection = mCurrentUrlConnection.get(); 515 HttpURLConnection connection = mCurrentUrlConnection.get();
497 if (connection == null) { 516 if (connection == null) {
498 return; // We've been cancelled 517 return; // We've been cancelled
499 } 518 }
500 final List<Map.Entry<String, String>> headerList = new ArrayList <>(); 519 final List<Map.Entry<String, String>> headerList = new ArrayList <>();
501 String selectedTransport = "http/1.1"; 520 String selectedTransport = "http/1.1";
502 String headerKey; 521 String headerKey;
503 for (int i = 0; (headerKey = connection.getHeaderFieldKey(i)) != null; i++) { 522 for (int i = 0; (headerKey = connection.getHeaderFieldKey(i)) != null; i++) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 public void run() { 581 public void run() {
563 mCallbackAsync.onRedirectReceived( 582 mCallbackAsync.onRedirectReceived(
564 mUrlResponseInfo, mPendingRedirectUrl); 583 mUrlResponseInfo, mPendingRedirectUrl);
565 } 584 }
566 }); 585 });
567 } 586 }
568 }); 587 });
569 } 588 }
570 589
571 private void fireOpenConnection() { 590 private void fireOpenConnection() {
572 mExecutor.execute(errorSetting(State.STARTED, new CheckedRunnable() { 591 mExecutor.execute(errorSetting(new CheckedRunnable() {
573 @Override 592 @Override
574 public void run() throws Exception { 593 public void run() throws Exception {
575 // If we're cancelled, then our old connection will be disconnec ted for us and 594 // If we're cancelled, then our old connection will be disconnec ted for us and
576 // we shouldn't open a new one. 595 // we shouldn't open a new one.
577 if (mState.get() == State.CANCELLED) { 596 if (mState.get() == State.CANCELLED) {
578 return; 597 return;
579 } 598 }
580 599
581 final URL url = new URL(mCurrentUrl); 600 final URL url = new URL(mCurrentUrl);
582 HttpURLConnection newConnection = (HttpURLConnection) url.openCo nnection(); 601 HttpURLConnection newConnection = (HttpURLConnection) url.openCo nnection();
(...skipping 18 matching lines...) Expand all
601 dataSink.start(mUrlChain.size() == 1); 620 dataSink.start(mUrlChain.size() == 1);
602 } else { 621 } else {
603 mAdditionalStatusDetails = Status.CONNECTING; 622 mAdditionalStatusDetails = Status.CONNECTING;
604 newConnection.connect(); 623 newConnection.connect();
605 fireGetHeaders(); 624 fireGetHeaders();
606 } 625 }
607 } 626 }
608 })); 627 }));
609 } 628 }
610 629
611 private Runnable errorSetting(final State expectedState, final CheckedRunnab le delegate) { 630 private Runnable errorSetting(final CheckedRunnable delegate) {
612 return new Runnable() { 631 return new Runnable() {
613 @Override 632 @Override
614 public void run() { 633 public void run() {
615 try { 634 try {
616 delegate.run(); 635 delegate.run();
617 } catch (Throwable t) { 636 } catch (Throwable t) {
618 enterCronetErrorState(expectedState, t); 637 enterCronetErrorState(t);
619 } 638 }
620 } 639 }
621 }; 640 };
622 } 641 }
623 642
624 private Runnable userErrorSetting(final State expectedState, final CheckedRu nnable delegate) { 643 private Runnable userErrorSetting(final CheckedRunnable delegate) {
625 return new Runnable() { 644 return new Runnable() {
626 @Override 645 @Override
627 public void run() { 646 public void run() {
628 try { 647 try {
629 delegate.run(); 648 delegate.run();
630 } catch (Throwable t) { 649 } catch (Throwable t) {
631 enterUserErrorState(expectedState, t); 650 enterUserErrorState(t);
632 } 651 }
633 } 652 }
634 }; 653 };
635 } 654 }
636 655
637 private Runnable uploadErrorSetting(final CheckedRunnable delegate) { 656 private Runnable uploadErrorSetting(final CheckedRunnable delegate) {
638 return new Runnable() { 657 return new Runnable() {
639 @Override 658 @Override
640 public void run() { 659 public void run() {
641 try { 660 try {
642 delegate.run(); 661 delegate.run();
643 } catch (Throwable t) { 662 } catch (Throwable t) {
644 enterUploadErrorState(t); 663 enterUploadErrorState(t);
645 } 664 }
646 } 665 }
647 }; 666 };
648 } 667 }
649 668
650 private interface CheckedRunnable { void run() throws Exception; } 669 private interface CheckedRunnable { void run() throws Exception; }
651 670
652 @Override 671 @Override
653 public void read(final ByteBuffer buffer) { 672 public void read(final ByteBuffer buffer) {
654 Preconditions.checkDirect(buffer); 673 Preconditions.checkDirect(buffer);
655 Preconditions.checkHasRemaining(buffer); 674 Preconditions.checkHasRemaining(buffer);
656 transitionStates(State.AWAITING_READ, State.READING, new Runnable() { 675 transitionStates(State.AWAITING_READ, State.READING, new Runnable() {
657 @Override 676 @Override
658 public void run() { 677 public void run() {
659 mExecutor.execute(errorSetting(State.READING, new CheckedRunnabl e() { 678 mExecutor.execute(errorSetting(new CheckedRunnable() {
660 @Override 679 @Override
661 public void run() throws Exception { 680 public void run() throws Exception {
662 int read = mResponseChannel.read(buffer); 681 int read = mResponseChannel.read(buffer);
663 processReadResult(read, buffer); 682 processReadResult(read, buffer);
664 } 683 }
665 })); 684 }));
666 } 685 }
667 }); 686 });
668 } 687 }
669 688
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 793
775 void sendStatus(final StatusListener listener, final int status) { 794 void sendStatus(final StatusListener listener, final int status) {
776 mUserExecutor.execute(new Runnable() { 795 mUserExecutor.execute(new Runnable() {
777 @Override 796 @Override
778 public void run() { 797 public void run() {
779 listener.onStatus(status); 798 listener.onStatus(status);
780 } 799 }
781 }); 800 });
782 } 801 }
783 802
784 void execute(State currentState, CheckedRunnable runnable) { 803 void execute(CheckedRunnable runnable) {
785 try { 804 try {
786 mUserExecutor.execute(userErrorSetting(currentState, runnable)); 805 mUserExecutor.execute(userErrorSetting(runnable));
787 } catch (RejectedExecutionException e) { 806 } catch (RejectedExecutionException e) {
788 enterErrorState(currentState, 807 enterErrorState(new UrlRequestException("Exception posting task to executor", e));
789 new UrlRequestException("Exception posting task to execu tor", e));
790 } 808 }
791 } 809 }
792 810
793 void onRedirectReceived(final UrlResponseInfo info, final String newLoca tionUrl) { 811 void onRedirectReceived(final UrlResponseInfo info, final String newLoca tionUrl) {
794 execute(State.AWAITING_FOLLOW_REDIRECT, new CheckedRunnable() { 812 execute(new CheckedRunnable() {
795 @Override 813 @Override
796 public void run() throws Exception { 814 public void run() throws Exception {
797 mCallback.onRedirectReceived(JavaUrlRequest.this, info, newL ocationUrl); 815 mCallback.onRedirectReceived(JavaUrlRequest.this, info, newL ocationUrl);
798 } 816 }
799 }); 817 });
800 } 818 }
801 819
802 void onResponseStarted(UrlResponseInfo info) { 820 void onResponseStarted(UrlResponseInfo info) {
803 if (mState.compareAndSet(State.STARTED, State.AWAITING_READ)) { 821 execute(new CheckedRunnable() {
804 execute(State.AWAITING_READ, new CheckedRunnable() { 822 @Override
805 @Override 823 public void run() throws Exception {
806 public void run() throws Exception { 824 if (mState.compareAndSet(State.STARTED, State.AWAITING_READ) ) {
807 mCallback.onResponseStarted(JavaUrlRequest.this, mUrlRes ponseInfo); 825 mCallback.onResponseStarted(JavaUrlRequest.this, mUrlRes ponseInfo);
808 } 826 }
809 }); 827 }
810 } 828 });
811 } 829 }
812 830
813 void onReadCompleted(final UrlResponseInfo info, final ByteBuffer byteBu ffer) { 831 void onReadCompleted(final UrlResponseInfo info, final ByteBuffer byteBu ffer) {
814 if (mState.compareAndSet(State.READING, State.AWAITING_READ)) { 832 execute(new CheckedRunnable() {
815 execute(State.AWAITING_READ, new CheckedRunnable() { 833 @Override
816 @Override 834 public void run() throws Exception {
817 public void run() throws Exception { 835 if (mState.compareAndSet(State.READING, State.AWAITING_READ) ) {
818 mCallback.onReadCompleted(JavaUrlRequest.this, info, byt eBuffer); 836 mCallback.onReadCompleted(JavaUrlRequest.this, info, byt eBuffer);
819 } 837 }
820 }); 838 }
821 } 839 });
822 } 840 }
823 841
824 void onCanceled(final UrlResponseInfo info) { 842 void onCanceled(final UrlResponseInfo info) {
825 closeResponseChannel(); 843 closeResponseChannel();
826 mUserExecutor.execute(new Runnable() { 844 mUserExecutor.execute(new Runnable() {
827 @Override 845 @Override
828 public void run() { 846 public void run() {
829 try { 847 try {
830 mCallback.onCanceled(JavaUrlRequest.this, info); 848 mCallback.onCanceled(JavaUrlRequest.this, info);
831 } catch (Exception exception) { 849 } catch (Exception exception) {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
931 // Can't throw directly from here, since the delegate execut or could catch this 949 // Can't throw directly from here, since the delegate execut or could catch this
932 // exception. 950 // exception.
933 mExecutedInline = new InlineExecutionProhibitedException(); 951 mExecutedInline = new InlineExecutionProhibitedException();
934 return; 952 return;
935 } 953 }
936 mCommand.run(); 954 mCommand.run();
937 } 955 }
938 } 956 }
939 } 957 }
940 } 958 }
OLDNEW
« no previous file with comments | « no previous file | components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestTest.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698