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.urlconnection; | 5 package org.chromium.net.urlconnection; |
6 | 6 |
| 7 import org.chromium.net.UploadDataProvider; |
7 import org.chromium.net.UploadDataSink; | 8 import org.chromium.net.UploadDataSink; |
8 | 9 |
9 import java.io.IOException; | 10 import java.io.IOException; |
10 import java.net.ProtocolException; | 11 import java.net.ProtocolException; |
11 import java.nio.ByteBuffer; | 12 import java.nio.ByteBuffer; |
12 | 13 |
13 /** | 14 /** |
14 * An implementation of {@link java.io.OutputStream} that buffers entire request | 15 * An implementation of {@link java.io.OutputStream} that buffers entire request |
15 * body in memory. This is used when neither | 16 * body in memory. This is used when neither |
16 * {@link CronetHttpURLConnection#setFixedLengthStreamingMode} | 17 * {@link CronetHttpURLConnection#setFixedLengthStreamingMode} |
17 * nor {@link CronetHttpURLConnection#setChunkedStreamingMode} is set. | 18 * nor {@link CronetHttpURLConnection#setChunkedStreamingMode} is set. |
18 */ | 19 */ |
19 final class CronetBufferedOutputStream extends CronetOutputStream { | 20 final class CronetBufferedOutputStream extends CronetOutputStream { |
20 // QUIC uses a read buffer of 14520 bytes, SPDY uses 2852 bytes, and normal | 21 // QUIC uses a read buffer of 14520 bytes, SPDY uses 2852 bytes, and normal |
21 // stream uses 16384 bytes. Therefore, use 16384 for now to avoid growing | 22 // stream uses 16384 bytes. Therefore, use 16384 for now to avoid growing |
22 // the buffer too many times. | 23 // the buffer too many times. |
23 private static final int INITIAL_BUFFER_SIZE = 16384; | 24 private static final int INITIAL_BUFFER_SIZE = 16384; |
24 // If content length is not passed in the constructor, this is -1. | 25 // If content length is not passed in the constructor, this is -1. |
25 private final int mInitialContentLength; | 26 private final int mInitialContentLength; |
26 private final CronetHttpURLConnection mConnection; | 27 private final CronetHttpURLConnection mConnection; |
| 28 private final UploadDataProvider mUploadDataProvider = new UploadDataProvide
rImpl(); |
27 // Internal buffer that is used to buffer the request body. | 29 // Internal buffer that is used to buffer the request body. |
28 private ByteBuffer mBuffer; | 30 private ByteBuffer mBuffer; |
29 private boolean mConnected = false; | 31 private boolean mConnected = false; |
30 | 32 |
31 /** | 33 /** |
32 * Package protected constructor. | 34 * Package protected constructor. |
33 * @param connection The CronetHttpURLConnection object. | 35 * @param connection The CronetHttpURLConnection object. |
34 * @param contentLength The content length of the request body. It must not | 36 * @param contentLength The content length of the request body. It must not |
35 * be smaller than 0 or bigger than {@link Integer.MAX_VALUE}. | 37 * be smaller than 0 or bigger than {@link Integer.MAX_VALUE}. |
36 */ | 38 */ |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 mBuffer.flip(); | 126 mBuffer.flip(); |
125 } | 127 } |
126 | 128 |
127 @Override | 129 @Override |
128 void checkReceivedEnoughContent() throws IOException { | 130 void checkReceivedEnoughContent() throws IOException { |
129 // Already checked in setConnected. Skip the check here, since mBuffer | 131 // Already checked in setConnected. Skip the check here, since mBuffer |
130 // might be flipped. | 132 // might be flipped. |
131 } | 133 } |
132 | 134 |
133 @Override | 135 @Override |
134 public long getLength() { | 136 UploadDataProvider getUploadDataProvider() { |
135 // This method is supposed to be called just before starting the request
. | 137 return mUploadDataProvider; |
136 // If content length is not initially passed in, the number of bytes | |
137 // written will be used as the content length. | |
138 // TODO(xunjieli): Think of a less fragile way, since getLength() can be | |
139 // potentially called in other places in the future. | |
140 if (mInitialContentLength == -1) { | |
141 return mBuffer.position(); | |
142 } | |
143 return mInitialContentLength; | |
144 } | 138 } |
145 | 139 |
146 @Override | 140 private class UploadDataProviderImpl extends UploadDataProvider { |
147 public void read(UploadDataSink uploadDataSink, ByteBuffer byteBuffer) { | 141 @Override |
148 int availableSpace = byteBuffer.capacity() - byteBuffer.position(); | 142 public long getLength() { |
149 if (availableSpace < mBuffer.limit() - mBuffer.position()) { | 143 // This method is supposed to be called just before starting the req
uest. |
150 byteBuffer.put(mBuffer.array(), mBuffer.position(), availableSpace); | 144 // If content length is not initially passed in, the number of bytes |
151 mBuffer.position(mBuffer.position() + availableSpace); | 145 // written will be used as the content length. |
152 } else { | 146 // TODO(xunjieli): Think of a less fragile way, since getLength() ca
n be |
153 byteBuffer.put(mBuffer); | 147 // potentially called in other places in the future. |
| 148 if (mInitialContentLength == -1) { |
| 149 return mBuffer.position(); |
| 150 } |
| 151 return mInitialContentLength; |
154 } | 152 } |
155 uploadDataSink.onReadSucceeded(false); | |
156 } | |
157 | 153 |
158 @Override | 154 @Override |
159 public void rewind(UploadDataSink uploadDataSink) { | 155 public void read(UploadDataSink uploadDataSink, ByteBuffer byteBuffer) { |
160 mBuffer.position(0); | 156 int availableSpace = byteBuffer.capacity() - byteBuffer.position(); |
161 uploadDataSink.onRewindSucceeded(); | 157 if (availableSpace < mBuffer.limit() - mBuffer.position()) { |
| 158 byteBuffer.put(mBuffer.array(), mBuffer.position(), availableSpa
ce); |
| 159 mBuffer.position(mBuffer.position() + availableSpace); |
| 160 } else { |
| 161 byteBuffer.put(mBuffer); |
| 162 } |
| 163 uploadDataSink.onReadSucceeded(false); |
| 164 } |
| 165 |
| 166 @Override |
| 167 public void rewind(UploadDataSink uploadDataSink) { |
| 168 mBuffer.position(0); |
| 169 uploadDataSink.onRewindSucceeded(); |
| 170 } |
162 } | 171 } |
163 } | 172 } |
OLD | NEW |