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

Side by Side Diff: components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java

Issue 725683002: [Cronet] Initial implementation of HttpURLConnection (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Get data only when required Created 6 years, 1 month 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
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.net.urlconnection;
6
7 import org.chromium.net.ExtendedResponseInfo;
8 import org.chromium.net.ResponseInfo;
9 import org.chromium.net.UrlRequest;
10 import org.chromium.net.UrlRequestContext;
11 import org.chromium.net.UrlRequestException;
12 import org.chromium.net.UrlRequestListener;
13
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.net.HttpURLConnection;
17 import java.net.URL;
18 import java.nio.ByteBuffer;
19 import java.util.concurrent.BlockingQueue;
20 import java.util.concurrent.Executor;
21 import java.util.concurrent.LinkedBlockingQueue;
22
23 /**
24 * An implementation of HttpURLConnection that uses Cronet to send requests and
25 * receive response. This class inherits a {@code connected} field from the
26 * superclass. That field indicates whether a connection has ever been
27 * attempted.
28 */
29 public class CronetHttpURLConnection extends HttpURLConnection {
30 private final UrlRequestContext mUrlRequestContext;
31 private final MessageLoop mMessageLoop;
32 private final BlockingQueue<MessageLoop.Message> mMessageQueue;
33
34 private UrlRequest mRequest;
35 private ResponseInfo mResponseInfo;
36 private ByteBufferInputStream mResponseBody;
37 private ByteBuffer mResponseByteBuffer;
38
39 protected CronetHttpURLConnection(URL url,
40 UrlRequestContext urlRequestContext) {
41 super(url);
42 mUrlRequestContext = urlRequestContext;
43 mMessageQueue = new LinkedBlockingQueue<MessageLoop.Message>();
44 mMessageLoop = new MessageLoop(mMessageQueue);
45 }
46
47 /**
48 * Wrapper executor class which posts tasks to current looper.
49 */
50 private class HandlerThreadExecutor implements Executor {
51 public HandlerThreadExecutor() {
52 }
53
54 @Override
55 public void execute(Runnable command) {
56 try {
57 mMessageQueue.put(new MessageLoop.Message(command));
58 } catch (InterruptedException e) {
59 e.printStackTrace();
60 }
61 }
62 }
63
64 /**
65 * Opens a connection to the resource.
66 */
67 @Override
68 public void connect() throws IOException {
69 maybeStartRequest();
70 }
71
72 /**
73 * Releases this connection so that its resources may be either reused or
74 * closed.
75 */
76 @Override
77 public void disconnect() {
78 if (mResponseBody != null) {
79 try {
80 mResponseBody.close();
81 } catch (IOException e) {
82 e.printStackTrace();
83 }
84 }
85 }
86
87 /**
88 * Returns the response message returned by the remote HTTP server.
89 */
90 @Override
91 public String getResponseMessage() {
92 maybeStartRequest();
93 return mResponseInfo.getHttpStatusText();
94 }
95
96 /**
97 * Returns the response code returned by the remote HTTP server.
98 */
99 @Override
100 public int getResponseCode() {
101 maybeStartRequest();
102 return mResponseInfo.getHttpStatusCode();
103 }
104
105 /**
106 * Returns an InputStream for reading data from the resource pointed by this
107 * URLConnection.
108 */
109 @Override
110 public InputStream getInputStream() {
111 maybeStartRequest();
112 if (mResponseBody == null) {
113 mResponseBody = new ByteBufferInputStream(mMessageLoop);
114 }
115 return mResponseBody;
116 }
117
118 /**
119 * Adds the given property to the request header.
120 */
121 @Override
122 public final void addRequestProperty(String key, String value) {
123 setRequestProperty(key, value);
124 }
125
126 /**
127 * Sets the value of the specified request header field.
128 */
129 @Override
130 public final void setRequestProperty(String key, String value) {
131 if (connected) {
132 throw new IllegalStateException(
133 "Cannot set request property after connection is made");
134 }
135 maybeCreateRequest();
136 mRequest.addHeader(key, value);
137 }
138
139 /**
140 * Returns whether this connection uses a proxy server or not.
141 */
142 @Override
143 public boolean usingProxy() {
144 // TODO(xunjieli): implement this.
145 return false;
146 }
147
148 private class CronetUrlRequestListener implements UrlRequestListener {
149
150 public CronetUrlRequestListener() {
151 }
152
153 @Override
154 public void onResponseStarted(UrlRequest request, ResponseInfo info) {
155 mResponseInfo = info;
156 // Quits the message loop since we have the headers now.
157 mMessageLoop.quit();
158 }
159
160 @Override
161 public void onDataReceived(UrlRequest request, ResponseInfo info,
162 ByteBuffer byteBuffer) {
163 mResponseInfo = info;
164 mResponseByteBuffer = ByteBuffer.allocateDirect(byteBuffer.capacity( ));
xunjieli 2014/11/19 19:15:46 I thought about reusing old buffer, but the size o
165 mResponseByteBuffer.put(byteBuffer);
166 mResponseByteBuffer.rewind();
167 mResponseBody.setByteBuffer(mResponseByteBuffer);
168 mMessageLoop.quit();
169 }
170
171 @Override
172 public void onRedirect(UrlRequest request, ResponseInfo info,
173 String newLocationUrl) {
174 // TODO(xunjieli): Handle redirect.
175 mResponseInfo = info;
176 }
177
178 @Override
179 public void onSucceeded(UrlRequest request, ExtendedResponseInfo info) {
180 setResponseDataCompleted();
181 }
182
183 @Override
184 public void onFailed(UrlRequest request, ResponseInfo info,
185 UrlRequestException exception) {
186 // TODO(xunjieli): Handle failure.
187 setResponseDataCompleted();
188 }
189 }
190
191 /**
192 * On first call, creates and starts UrlRequest, and waits until response
193 * headers are received. Does nothing on subsequent calls.
194 */
195 private void maybeStartRequest() {
196 if (connected) {
197 return;
198 }
199 maybeCreateRequest();
200 mRequest.start();
201 connected = true;
202 // Blocks until onResponseStarted or onFailed is called.
203 mMessageLoop.loop();
204 }
205
206 /**
207 * Maybe creates {@code mRequest} if it is null.
208 */
209 private void maybeCreateRequest() {
210 if (mRequest != null) {
211 return;
212 }
213 mRequest = mUrlRequestContext.createRequest(url.toString(),
214 new CronetUrlRequestListener(), new HandlerThreadExecutor());
215 }
216
217 /**
218 * Notifies {@link #mResponseBody} that transferring of response data has
219 * completed.
220 */
221 private void setResponseDataCompleted() {
222 if (mResponseBody != null) {
223 mResponseBody.setResponseDataCompleted();
224 }
225 mMessageLoop.quit();
226 }
227 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698