| 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; | 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; |
| 11 | 11 |
| 12 import java.io.Closeable; | 12 import java.io.Closeable; |
| 13 import java.io.IOException; | 13 import java.io.IOException; |
| 14 import java.io.OutputStream; |
| 14 import java.net.HttpURLConnection; | 15 import java.net.HttpURLConnection; |
| 15 import java.net.URI; | 16 import java.net.URI; |
| 16 import java.net.URL; | 17 import java.net.URL; |
| 17 import java.nio.ByteBuffer; | 18 import java.nio.ByteBuffer; |
| 18 import java.nio.channels.Channels; | 19 import java.nio.channels.Channels; |
| 19 import java.nio.channels.ReadableByteChannel; | 20 import java.nio.channels.ReadableByteChannel; |
| 20 import java.nio.channels.WritableByteChannel; | 21 import java.nio.channels.WritableByteChannel; |
| 21 import java.util.AbstractMap.SimpleEntry; | 22 import java.util.AbstractMap.SimpleEntry; |
| 22 import java.util.ArrayList; | 23 import java.util.ArrayList; |
| 23 import java.util.Collections; | 24 import java.util.Collections; |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 UPLOADING, | 254 UPLOADING, |
| 254 NOT_STARTED, | 255 NOT_STARTED, |
| 255 } | 256 } |
| 256 | 257 |
| 257 private final class OutputStreamDataSink implements UploadDataSink { | 258 private final class OutputStreamDataSink implements UploadDataSink { |
| 258 final AtomicReference<SinkState> mSinkState = new AtomicReference<>(Sink
State.NOT_STARTED); | 259 final AtomicReference<SinkState> mSinkState = new AtomicReference<>(Sink
State.NOT_STARTED); |
| 259 final Executor mUserUploadExecutor; | 260 final Executor mUserUploadExecutor; |
| 260 final Executor mExecutor; | 261 final Executor mExecutor; |
| 261 final HttpURLConnection mUrlConnection; | 262 final HttpURLConnection mUrlConnection; |
| 262 WritableByteChannel mOutputChannel; | 263 WritableByteChannel mOutputChannel; |
| 264 OutputStream mUrlConnectionOutputStream; |
| 263 final UploadDataProvider mUploadProvider; | 265 final UploadDataProvider mUploadProvider; |
| 264 ByteBuffer mBuffer; | 266 ByteBuffer mBuffer; |
| 265 /** This holds the total bytes to send (the content-length). -1 if unkno
wn. */ | 267 /** This holds the total bytes to send (the content-length). -1 if unkno
wn. */ |
| 266 long mTotalBytes; | 268 long mTotalBytes; |
| 267 /** This holds the bytes written so far */ | 269 /** This holds the bytes written so far */ |
| 268 long mWrittenBytes = 0; | 270 long mWrittenBytes = 0; |
| 269 | 271 |
| 270 OutputStreamDataSink(final Executor userExecutor, Executor executor, | 272 OutputStreamDataSink(final Executor userExecutor, Executor executor, |
| 271 HttpURLConnection urlConnection, UploadDataProvider provider) { | 273 HttpURLConnection urlConnection, UploadDataProvider provider) { |
| 272 this.mUserUploadExecutor = new Executor() { | 274 this.mUserUploadExecutor = new Executor() { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 296 mBuffer.flip(); | 298 mBuffer.flip(); |
| 297 if (mTotalBytes != -1 && mTotalBytes - mWrittenBytes < mBuff
er.remaining()) { | 299 if (mTotalBytes != -1 && mTotalBytes - mWrittenBytes < mBuff
er.remaining()) { |
| 298 enterUploadErrorState(new IllegalArgumentException(Strin
g.format( | 300 enterUploadErrorState(new IllegalArgumentException(Strin
g.format( |
| 299 "Read upload data length %d exceeds expected len
gth %d", | 301 "Read upload data length %d exceeds expected len
gth %d", |
| 300 mWrittenBytes + mBuffer.remaining(), mTotalBytes
))); | 302 mWrittenBytes + mBuffer.remaining(), mTotalBytes
))); |
| 301 return; | 303 return; |
| 302 } | 304 } |
| 303 while (mBuffer.hasRemaining()) { | 305 while (mBuffer.hasRemaining()) { |
| 304 mWrittenBytes += mOutputChannel.write(mBuffer); | 306 mWrittenBytes += mOutputChannel.write(mBuffer); |
| 305 } | 307 } |
| 308 // Forces a chunk to be sent, rather than buffering to the D
EFAULT_CHUNK_LENGTH. |
| 309 // This allows clients to trickle-upload bytes as they becom
e available without |
| 310 // introducing latency due to buffering. |
| 311 mUrlConnectionOutputStream.flush(); |
| 312 |
| 306 if (mWrittenBytes < mTotalBytes || (mTotalBytes == -1 && !fi
nalChunk)) { | 313 if (mWrittenBytes < mTotalBytes || (mTotalBytes == -1 && !fi
nalChunk)) { |
| 307 mBuffer.clear(); | 314 mBuffer.clear(); |
| 308 mSinkState.set(SinkState.AWAITING_READ_RESULT); | 315 mSinkState.set(SinkState.AWAITING_READ_RESULT); |
| 309 executeOnUploadExecutor(new CheckedRunnable() { | 316 executeOnUploadExecutor(new CheckedRunnable() { |
| 310 @Override | 317 @Override |
| 311 public void run() throws Exception { | 318 public void run() throws Exception { |
| 312 mUploadProvider.read(OutputStreamDataSink.this,
mBuffer); | 319 mUploadProvider.read(OutputStreamDataSink.this,
mBuffer); |
| 313 } | 320 } |
| 314 }); | 321 }); |
| 315 } else if (mTotalBytes == -1) { | 322 } else if (mTotalBytes == -1) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 344 } | 351 } |
| 345 | 352 |
| 346 void startRead() { | 353 void startRead() { |
| 347 mExecutor.execute(errorSetting(new CheckedRunnable() { | 354 mExecutor.execute(errorSetting(new CheckedRunnable() { |
| 348 @Override | 355 @Override |
| 349 public void run() throws Exception { | 356 public void run() throws Exception { |
| 350 if (mOutputChannel == null) { | 357 if (mOutputChannel == null) { |
| 351 mAdditionalStatusDetails = Status.CONNECTING; | 358 mAdditionalStatusDetails = Status.CONNECTING; |
| 352 mUrlConnection.connect(); | 359 mUrlConnection.connect(); |
| 353 mAdditionalStatusDetails = Status.SENDING_REQUEST; | 360 mAdditionalStatusDetails = Status.SENDING_REQUEST; |
| 354 mOutputChannel = Channels.newChannel(mUrlConnection.getO
utputStream()); | 361 mUrlConnectionOutputStream = mUrlConnection.getOutputStr
eam(); |
| 362 mOutputChannel = Channels.newChannel(mUrlConnectionOutpu
tStream); |
| 355 } | 363 } |
| 356 mSinkState.set(SinkState.AWAITING_READ_RESULT); | 364 mSinkState.set(SinkState.AWAITING_READ_RESULT); |
| 357 executeOnUploadExecutor(new CheckedRunnable() { | 365 executeOnUploadExecutor(new CheckedRunnable() { |
| 358 @Override | 366 @Override |
| 359 public void run() throws Exception { | 367 public void run() throws Exception { |
| 360 mUploadProvider.read(OutputStreamDataSink.this, mBuf
fer); | 368 mUploadProvider.read(OutputStreamDataSink.this, mBuf
fer); |
| 361 } | 369 } |
| 362 }); | 370 }); |
| 363 } | 371 } |
| 364 })); | 372 })); |
| (...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 949 // Can't throw directly from here, since the delegate execut
or could catch this | 957 // Can't throw directly from here, since the delegate execut
or could catch this |
| 950 // exception. | 958 // exception. |
| 951 mExecutedInline = new InlineExecutionProhibitedException(); | 959 mExecutedInline = new InlineExecutionProhibitedException(); |
| 952 return; | 960 return; |
| 953 } | 961 } |
| 954 mCommand.run(); | 962 mCommand.run(); |
| 955 } | 963 } |
| 956 } | 964 } |
| 957 } | 965 } |
| 958 } | 966 } |
| OLD | NEW |