| OLD | NEW |
| 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.impl; | 5 package org.chromium.net.impl; |
| 6 | 6 |
| 7 import android.annotation.SuppressLint; | 7 import android.annotation.SuppressLint; |
| 8 import android.annotation.TargetApi; | 8 import android.annotation.TargetApi; |
| 9 import android.net.TrafficStats; | 9 import android.net.TrafficStats; |
| 10 import android.os.Build; | 10 import android.os.Build; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 /** | 70 /** |
| 71 * Traffic stats tag to associate this requests' data use with. It's capture
d when the request | 71 * Traffic stats tag to associate this requests' data use with. It's capture
d when the request |
| 72 * is created, so that applications doing work on behalf of another app can
correctly attribute | 72 * is created, so that applications doing work on behalf of another app can
correctly attribute |
| 73 * that data use. | 73 * that data use. |
| 74 */ | 74 */ |
| 75 private final int mTrafficStatsTag; | 75 private final int mTrafficStatsTag; |
| 76 private final boolean mAllowDirectExecutor; | 76 private final boolean mAllowDirectExecutor; |
| 77 | 77 |
| 78 /* These don't change with redirects */ | 78 /* These don't change with redirects */ |
| 79 private String mInitialMethod; | 79 private String mInitialMethod; |
| 80 private UploadDataProvider mUploadDataProvider; | 80 private VersionSafeCallbacks.UploadDataProviderWrapper mUploadDataProvider; |
| 81 private Executor mUploadExecutor; | 81 private Executor mUploadExecutor; |
| 82 | 82 |
| 83 /** | 83 /** |
| 84 * Holds a subset of StatusValues - {@link State#STARTED} can represent | 84 * Holds a subset of StatusValues - {@link State#STARTED} can represent |
| 85 * {@link Status#SENDING_REQUEST} or {@link Status#WAITING_FOR_RESPONSE}. Wh
ile the distinction | 85 * {@link Status#SENDING_REQUEST} or {@link Status#WAITING_FOR_RESPONSE}. Wh
ile the distinction |
| 86 * isn't needed to implement the logic in this class, it is needed to implem
ent | 86 * isn't needed to implement the logic in this class, it is needed to implem
ent |
| 87 * {@link #getStatus(StatusListener)}. | 87 * {@link #getStatus(StatusListener)}. |
| 88 * | 88 * |
| 89 * <p>Concurrency notes - this value is not atomically updated with mState,
so there is some | 89 * <p>Concurrency notes - this value is not atomically updated with mState,
so there is some |
| 90 * risk that we'd get an inconsistent snapshot of both - however, it also ha
ppens that this | 90 * risk that we'd get an inconsistent snapshot of both - however, it also ha
ppens that this |
| 91 * value is only used with the STARTED state, so it's inconsequential. | 91 * value is only used with the STARTED state, so it's inconsequential. |
| 92 */ | 92 */ |
| 93 @StatusValues | 93 @StatusValues |
| 94 private volatile int mAdditionalStatusDetails = Status.INVALID; | 94 private volatile int mAdditionalStatusDetails = Status.INVALID; |
| 95 | 95 |
| 96 /* These change with redirects. */ | 96 /* These change with redirects. */ |
| 97 private String mCurrentUrl; | 97 private String mCurrentUrl; |
| 98 private ReadableByteChannel mResponseChannel; | 98 private ReadableByteChannel mResponseChannel; |
| 99 private UrlResponseInfo mUrlResponseInfo; | 99 private UrlResponseInfoImpl mUrlResponseInfo; |
| 100 private String mPendingRedirectUrl; | 100 private String mPendingRedirectUrl; |
| 101 /** | 101 /** |
| 102 * The happens-before edges created by the executor submission and AtomicRef
erence setting are | 102 * The happens-before edges created by the executor submission and AtomicRef
erence setting are |
| 103 * sufficient to guarantee the correct behavior of this field; however, this
is an | 103 * sufficient to guarantee the correct behavior of this field; however, this
is an |
| 104 * AtomicReference so that we can cleanly dispose of a new connection if we'
re cancelled during | 104 * AtomicReference so that we can cleanly dispose of a new connection if we'
re cancelled during |
| 105 * a redirect, which requires get-and-set semantics. | 105 * a redirect, which requires get-and-set semantics. |
| 106 * */ | 106 * */ |
| 107 private final AtomicReference<HttpURLConnection> mCurrentUrlConnection = | 107 private final AtomicReference<HttpURLConnection> mCurrentUrlConnection = |
| 108 new AtomicReference<>(); | 108 new AtomicReference<>(); |
| 109 | 109 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 throw new NullPointerException("Invalid UploadDataProvider."); | 242 throw new NullPointerException("Invalid UploadDataProvider."); |
| 243 } | 243 } |
| 244 if (!mRequestHeaders.containsKey("Content-Type")) { | 244 if (!mRequestHeaders.containsKey("Content-Type")) { |
| 245 throw new IllegalArgumentException( | 245 throw new IllegalArgumentException( |
| 246 "Requests with upload data must have a Content-Type."); | 246 "Requests with upload data must have a Content-Type."); |
| 247 } | 247 } |
| 248 checkNotStarted(); | 248 checkNotStarted(); |
| 249 if (mInitialMethod == null) { | 249 if (mInitialMethod == null) { |
| 250 mInitialMethod = "POST"; | 250 mInitialMethod = "POST"; |
| 251 } | 251 } |
| 252 this.mUploadDataProvider = uploadDataProvider; | 252 this.mUploadDataProvider = |
| 253 new VersionSafeCallbacks.UploadDataProviderWrapper(uploadDataPro
vider); |
| 253 if (mAllowDirectExecutor) { | 254 if (mAllowDirectExecutor) { |
| 254 this.mUploadExecutor = executor; | 255 this.mUploadExecutor = executor; |
| 255 } else { | 256 } else { |
| 256 this.mUploadExecutor = new DirectPreventingExecutor(executor); | 257 this.mUploadExecutor = new DirectPreventingExecutor(executor); |
| 257 } | 258 } |
| 258 } | 259 } |
| 259 | 260 |
| 260 private enum SinkState { | 261 private enum SinkState { |
| 261 AWAITING_READ_RESULT, | 262 AWAITING_READ_RESULT, |
| 262 AWAITING_REWIND_RESULT, | 263 AWAITING_REWIND_RESULT, |
| 263 UPLOADING, | 264 UPLOADING, |
| 264 NOT_STARTED, | 265 NOT_STARTED, |
| 265 } | 266 } |
| 266 | 267 |
| 267 private final class OutputStreamDataSink extends UploadDataSink { | 268 private final class OutputStreamDataSink extends UploadDataSink { |
| 268 final AtomicReference<SinkState> mSinkState = new AtomicReference<>(Sink
State.NOT_STARTED); | 269 final AtomicReference<SinkState> mSinkState = new AtomicReference<>(Sink
State.NOT_STARTED); |
| 269 final Executor mUserUploadExecutor; | 270 final Executor mUserUploadExecutor; |
| 270 final Executor mExecutor; | 271 final Executor mExecutor; |
| 271 final HttpURLConnection mUrlConnection; | 272 final HttpURLConnection mUrlConnection; |
| 272 WritableByteChannel mOutputChannel; | 273 WritableByteChannel mOutputChannel; |
| 273 OutputStream mUrlConnectionOutputStream; | 274 OutputStream mUrlConnectionOutputStream; |
| 274 final UploadDataProvider mUploadProvider; | 275 final VersionSafeCallbacks.UploadDataProviderWrapper mUploadProvider; |
| 275 ByteBuffer mBuffer; | 276 ByteBuffer mBuffer; |
| 276 /** This holds the total bytes to send (the content-length). -1 if unkno
wn. */ | 277 /** This holds the total bytes to send (the content-length). -1 if unkno
wn. */ |
| 277 long mTotalBytes; | 278 long mTotalBytes; |
| 278 /** This holds the bytes written so far */ | 279 /** This holds the bytes written so far */ |
| 279 long mWrittenBytes = 0; | 280 long mWrittenBytes = 0; |
| 280 | 281 |
| 281 OutputStreamDataSink(final Executor userExecutor, Executor executor, | 282 OutputStreamDataSink(final Executor userExecutor, Executor executor, |
| 282 HttpURLConnection urlConnection, UploadDataProvider provider) { | 283 HttpURLConnection urlConnection, |
| 284 VersionSafeCallbacks.UploadDataProviderWrapper provider) { |
| 283 this.mUserUploadExecutor = new Executor() { | 285 this.mUserUploadExecutor = new Executor() { |
| 284 @Override | 286 @Override |
| 285 public void execute(Runnable runnable) { | 287 public void execute(Runnable runnable) { |
| 286 try { | 288 try { |
| 287 userExecutor.execute(runnable); | 289 userExecutor.execute(runnable); |
| 288 } catch (RejectedExecutionException e) { | 290 } catch (RejectedExecutionException e) { |
| 289 enterUploadErrorState(e); | 291 enterUploadErrorState(e); |
| 290 } | 292 } |
| 291 } | 293 } |
| 292 }; | 294 }; |
| (...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 783 case AWAITING_READ: | 785 case AWAITING_READ: |
| 784 status = Status.IDLE; | 786 status = Status.IDLE; |
| 785 break; | 787 break; |
| 786 case READING: | 788 case READING: |
| 787 status = Status.READING_RESPONSE; | 789 status = Status.READING_RESPONSE; |
| 788 break; | 790 break; |
| 789 default: | 791 default: |
| 790 throw new IllegalStateException("Switch is exhaustive: " + state
); | 792 throw new IllegalStateException("Switch is exhaustive: " + state
); |
| 791 } | 793 } |
| 792 | 794 |
| 793 mCallbackAsync.sendStatus(listener, status); | 795 mCallbackAsync.sendStatus( |
| 796 new VersionSafeCallbacks.UrlRequestStatusListener(listener), sta
tus); |
| 794 } | 797 } |
| 795 | 798 |
| 796 /** This wrapper ensures that callbacks are always called on the correct exe
cutor */ | 799 /** This wrapper ensures that callbacks are always called on the correct exe
cutor */ |
| 797 private final class AsyncUrlRequestCallback { | 800 private final class AsyncUrlRequestCallback { |
| 798 final Callback mCallback; | 801 final VersionSafeCallbacks.UrlRequestCallback mCallback; |
| 799 final Executor mUserExecutor; | 802 final Executor mUserExecutor; |
| 800 final Executor mFallbackExecutor; | 803 final Executor mFallbackExecutor; |
| 801 | 804 |
| 802 AsyncUrlRequestCallback(Callback callback, final Executor userExecutor)
{ | 805 AsyncUrlRequestCallback(Callback callback, final Executor userExecutor)
{ |
| 803 this.mCallback = callback; | 806 this.mCallback = new VersionSafeCallbacks.UrlRequestCallback(callbac
k); |
| 804 if (mAllowDirectExecutor) { | 807 if (mAllowDirectExecutor) { |
| 805 this.mUserExecutor = userExecutor; | 808 this.mUserExecutor = userExecutor; |
| 806 this.mFallbackExecutor = null; | 809 this.mFallbackExecutor = null; |
| 807 } else { | 810 } else { |
| 808 mUserExecutor = new DirectPreventingExecutor(userExecutor); | 811 mUserExecutor = new DirectPreventingExecutor(userExecutor); |
| 809 mFallbackExecutor = userExecutor; | 812 mFallbackExecutor = userExecutor; |
| 810 } | 813 } |
| 811 } | 814 } |
| 812 | 815 |
| 813 void sendStatus(final StatusListener listener, final int status) { | 816 void sendStatus( |
| 817 final VersionSafeCallbacks.UrlRequestStatusListener listener, fi
nal int status) { |
| 814 mUserExecutor.execute(new Runnable() { | 818 mUserExecutor.execute(new Runnable() { |
| 815 @Override | 819 @Override |
| 816 public void run() { | 820 public void run() { |
| 817 listener.onStatus(status); | 821 listener.onStatus(status); |
| 818 } | 822 } |
| 819 }); | 823 }); |
| 820 } | 824 } |
| 821 | 825 |
| 822 void execute(CheckedRunnable runnable) { | 826 void execute(CheckedRunnable runnable) { |
| 823 try { | 827 try { |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 968 // Can't throw directly from here, since the delegate execut
or could catch this | 972 // Can't throw directly from here, since the delegate execut
or could catch this |
| 969 // exception. | 973 // exception. |
| 970 mExecutedInline = new InlineExecutionProhibitedException(); | 974 mExecutedInline = new InlineExecutionProhibitedException(); |
| 971 return; | 975 return; |
| 972 } | 976 } |
| 973 mCommand.run(); | 977 mCommand.run(); |
| 974 } | 978 } |
| 975 } | 979 } |
| 976 } | 980 } |
| 977 } | 981 } |
| OLD | NEW |