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.HttpRetryException; | 11 import java.net.HttpRetryException; |
11 import java.nio.ByteBuffer; | 12 import java.nio.ByteBuffer; |
12 | 13 |
13 /** | 14 /** |
14 * An implementation of {@link java.io.OutputStream} to send data to a server, | 15 * An implementation of {@link java.io.OutputStream} to send data to a server, |
15 * when {@link CronetHttpURLConnection#setChunkedStreamingMode} is used. | 16 * when {@link CronetHttpURLConnection#setChunkedStreamingMode} is used. |
16 * This implementation does not buffer the entire request body in memory. | 17 * This implementation does not buffer the entire request body in memory. |
17 * It does not support rewind. Note that {@link #write} should only be called | 18 * It does not support rewind. Note that {@link #write} should only be called |
18 * from the thread on which the {@link #mConnection} is created. | 19 * from the thread on which the {@link #mConnection} is created. |
19 */ | 20 */ |
20 final class CronetChunkedOutputStream extends CronetOutputStream { | 21 final class CronetChunkedOutputStream extends CronetOutputStream { |
21 private final CronetHttpURLConnection mConnection; | 22 private final CronetHttpURLConnection mConnection; |
22 private final MessageLoop mMessageLoop; | 23 private final MessageLoop mMessageLoop; |
23 private final ByteBuffer mBuffer; | 24 private final ByteBuffer mBuffer; |
| 25 private final UploadDataProvider mUploadDataProvider = new UploadDataProvide
rImpl(); |
24 private long mBytesWritten; | 26 private long mBytesWritten; |
25 private boolean mLastChunk = false; | 27 private boolean mLastChunk = false; |
26 private boolean mClosed = false; | 28 private boolean mClosed = false; |
27 | 29 |
28 /** | 30 /** |
29 * Package protected constructor. | 31 * Package protected constructor. |
30 * @param connection The CronetHttpURLConnection object. | 32 * @param connection The CronetHttpURLConnection object. |
31 * @param contentLength The content length of the request body. Non-zero for | 33 * @param contentLength The content length of the request body. Non-zero for |
32 * non-chunked upload. | 34 * non-chunked upload. |
33 */ | 35 */ |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 void setConnected() throws IOException { | 102 void setConnected() throws IOException { |
101 // Do nothing. | 103 // Do nothing. |
102 } | 104 } |
103 | 105 |
104 @Override | 106 @Override |
105 void checkReceivedEnoughContent() throws IOException { | 107 void checkReceivedEnoughContent() throws IOException { |
106 // Do nothing. | 108 // Do nothing. |
107 } | 109 } |
108 | 110 |
109 @Override | 111 @Override |
110 public long getLength() { | 112 UploadDataProvider getUploadDataProvider() { |
111 return -1; | 113 return mUploadDataProvider; |
112 } | 114 } |
113 | 115 |
114 @Override | 116 private class UploadDataProviderImpl extends UploadDataProvider { |
115 public void read(final UploadDataSink uploadDataSink, final ByteBuffer byteB
uffer) { | 117 @Override |
116 int availableSpace = byteBuffer.capacity() - byteBuffer.position(); | 118 public long getLength() { |
117 if (availableSpace < mBuffer.position()) { | 119 return -1; |
118 // byteBuffer does not have enough capacity, so only put a portion | 120 } |
119 // of mBuffer in it. | 121 |
120 byteBuffer.put(mBuffer.array(), 0, availableSpace); | 122 @Override |
121 mBuffer.position(availableSpace); | 123 public void read(final UploadDataSink uploadDataSink, final ByteBuffer b
yteBuffer) { |
122 // Move remaining buffer to the head of the buffer for use in the | 124 int availableSpace = byteBuffer.capacity() - byteBuffer.position(); |
123 // next read call. | 125 if (availableSpace < mBuffer.position()) { |
124 mBuffer.compact(); | 126 // byteBuffer does not have enough capacity, so only put a porti
on |
125 uploadDataSink.onReadSucceeded(false); | 127 // of mBuffer in it. |
126 } else { | 128 byteBuffer.put(mBuffer.array(), 0, availableSpace); |
127 // byteBuffer has enough capacity to hold the content of mBuffer. | 129 mBuffer.position(availableSpace); |
128 mBuffer.flip(); | 130 // Move remaining buffer to the head of the buffer for use in th
e |
129 byteBuffer.put(mBuffer); | 131 // next read call. |
130 // Reuse this buffer. | 132 mBuffer.compact(); |
131 mBuffer.clear(); | 133 uploadDataSink.onReadSucceeded(false); |
132 // Quit message loop so embedder can write more data. | 134 } else { |
133 mMessageLoop.quit(); | 135 // byteBuffer has enough capacity to hold the content of mBuffer
. |
134 uploadDataSink.onReadSucceeded(mLastChunk); | 136 mBuffer.flip(); |
| 137 byteBuffer.put(mBuffer); |
| 138 // Reuse this buffer. |
| 139 mBuffer.clear(); |
| 140 // Quit message loop so embedder can write more data. |
| 141 mMessageLoop.quit(); |
| 142 uploadDataSink.onReadSucceeded(mLastChunk); |
| 143 } |
| 144 } |
| 145 |
| 146 @Override |
| 147 public void rewind(UploadDataSink uploadDataSink) { |
| 148 uploadDataSink.onRewindError( |
| 149 new HttpRetryException("Cannot retry streamed Http body", -1
)); |
135 } | 150 } |
136 } | 151 } |
137 | |
138 @Override | |
139 public void rewind(UploadDataSink uploadDataSink) { | |
140 uploadDataSink.onRewindError(new HttpRetryException("Cannot retry stream
ed Http body", -1)); | |
141 } | |
142 } | 152 } |
OLD | NEW |