Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / components / cronet / android / chromium_url_request.cc
blob239c024f9dfa5cee67176083af92e66f82cd2f0e
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.
5 #include "components/cronet/android/chromium_url_request.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/macros.h"
10 #include "components/cronet/android/url_request_adapter.h"
11 #include "components/cronet/android/url_request_context_adapter.h"
12 #include "jni/ChromiumUrlRequest_jni.h"
13 #include "net/base/net_errors.h"
14 #include "net/base/request_priority.h"
15 #include "net/http/http_response_headers.h"
17 using base::android::ConvertUTF8ToJavaString;
18 using base::android::ConvertJavaStringToUTF8;
20 namespace cronet {
21 namespace {
23 net::RequestPriority ConvertRequestPriority(jint request_priority) {
24 switch (request_priority) {
25 case REQUEST_PRIORITY_IDLE:
26 return net::IDLE;
27 case REQUEST_PRIORITY_LOWEST:
28 return net::LOWEST;
29 case REQUEST_PRIORITY_LOW:
30 return net::LOW;
31 case REQUEST_PRIORITY_MEDIUM:
32 return net::MEDIUM;
33 case REQUEST_PRIORITY_HIGHEST:
34 return net::HIGHEST;
35 default:
36 return net::LOWEST;
40 void SetPostContentType(JNIEnv* env,
41 URLRequestAdapter* request_adapter,
42 jstring content_type) {
43 DCHECK(request_adapter);
45 std::string method_post("POST");
46 request_adapter->SetMethod(method_post);
48 std::string content_type_header("Content-Type");
49 std::string content_type_string(ConvertJavaStringToUTF8(env, content_type));
51 request_adapter->AddHeader(content_type_header, content_type_string);
54 // A delegate of URLRequestAdapter that delivers callbacks to the Java layer.
55 class JniURLRequestAdapterDelegate
56 : public URLRequestAdapter::URLRequestAdapterDelegate {
57 public:
58 JniURLRequestAdapterDelegate(JNIEnv* env, jobject owner) {
59 owner_ = env->NewGlobalRef(owner);
62 void OnResponseStarted(URLRequestAdapter* request_adapter) override {
63 JNIEnv* env = base::android::AttachCurrentThread();
64 cronet::Java_ChromiumUrlRequest_onResponseStarted(env, owner_);
67 void OnBytesRead(URLRequestAdapter* request_adapter) override {
68 int bytes_read = request_adapter->bytes_read();
69 if (bytes_read != 0) {
70 JNIEnv* env = base::android::AttachCurrentThread();
71 base::android::ScopedJavaLocalRef<jobject> java_buffer(
72 env, env->NewDirectByteBuffer(request_adapter->Data(), bytes_read));
73 cronet::Java_ChromiumUrlRequest_onBytesRead(
74 env, owner_, java_buffer.obj());
78 void OnRequestFinished(URLRequestAdapter* request_adapter) override {
79 JNIEnv* env = base::android::AttachCurrentThread();
80 cronet::Java_ChromiumUrlRequest_finish(env, owner_);
83 int ReadFromUploadChannel(net::IOBuffer* buf, int buf_length) override {
84 JNIEnv* env = base::android::AttachCurrentThread();
85 base::android::ScopedJavaLocalRef<jobject> java_buffer(
86 env, env->NewDirectByteBuffer(buf->data(), buf_length));
87 jint bytes_read = cronet::Java_ChromiumUrlRequest_readFromUploadChannel(
88 env, owner_, java_buffer.obj());
89 return bytes_read;
92 protected:
93 ~JniURLRequestAdapterDelegate() override {
94 JNIEnv* env = base::android::AttachCurrentThread();
95 env->DeleteGlobalRef(owner_);
98 private:
99 jobject owner_;
101 DISALLOW_COPY_AND_ASSIGN(JniURLRequestAdapterDelegate);
104 } // namespace
106 // Explicitly register static JNI functions.
107 bool ChromiumUrlRequestRegisterJni(JNIEnv* env) {
108 return RegisterNativesImpl(env);
111 static jlong CreateRequestAdapter(JNIEnv* env,
112 jobject jcaller,
113 jlong jurl_request_context_adapter,
114 jstring jurl,
115 jint jrequest_priority) {
116 URLRequestContextAdapter* context_adapter =
117 reinterpret_cast<URLRequestContextAdapter*>(jurl_request_context_adapter);
118 DCHECK(context_adapter);
120 GURL url(ConvertJavaStringToUTF8(env, jurl));
122 VLOG(1) << "New chromium network request: " << url.possibly_invalid_spec();
124 URLRequestAdapter* adapter = new URLRequestAdapter(
125 context_adapter, new JniURLRequestAdapterDelegate(env, jcaller), url,
126 ConvertRequestPriority(jrequest_priority));
128 return reinterpret_cast<jlong>(adapter);
131 // synchronized
132 static void AddHeader(JNIEnv* env,
133 jobject jcaller,
134 jlong jurl_request_adapter,
135 jstring jheader_name,
136 jstring jheader_value) {
137 URLRequestAdapter* request_adapter =
138 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
139 DCHECK(request_adapter);
141 std::string header_name(ConvertJavaStringToUTF8(env, jheader_name));
142 std::string header_value(ConvertJavaStringToUTF8(env, jheader_value));
144 request_adapter->AddHeader(header_name, header_value);
147 static void SetMethod(JNIEnv* env,
148 jobject jcaller,
149 jlong jurl_request_adapter,
150 jstring jmethod) {
151 URLRequestAdapter* request_adapter =
152 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
153 DCHECK(request_adapter);
155 std::string method(ConvertJavaStringToUTF8(env, jmethod));
157 request_adapter->SetMethod(method);
160 static void SetUploadData(JNIEnv* env,
161 jobject jcaller,
162 jlong jurl_request_adapter,
163 jstring jcontent_type,
164 jbyteArray jcontent) {
165 URLRequestAdapter* request_adapter =
166 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
167 SetPostContentType(env, request_adapter, jcontent_type);
169 if (jcontent != NULL) {
170 jsize size = env->GetArrayLength(jcontent);
171 if (size > 0) {
172 jbyte* content_bytes = env->GetByteArrayElements(jcontent, NULL);
173 request_adapter->SetUploadContent(
174 reinterpret_cast<const char*>(content_bytes), size);
175 env->ReleaseByteArrayElements(jcontent, content_bytes, 0);
180 static void SetUploadChannel(JNIEnv* env,
181 jobject jcaller,
182 jlong jurl_request_adapter,
183 jstring jcontent_type,
184 jlong jcontent_length) {
185 URLRequestAdapter* request_adapter =
186 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
187 SetPostContentType(env, request_adapter, jcontent_type);
189 request_adapter->SetUploadChannel(env, jcontent_length);
192 static void EnableChunkedUpload(JNIEnv* env,
193 jobject jcaller,
194 jlong jurl_request_adapter,
195 jstring jcontent_type) {
196 URLRequestAdapter* request_adapter =
197 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
198 SetPostContentType(env, request_adapter, jcontent_type);
200 request_adapter->EnableChunkedUpload();
203 static void AppendChunk(JNIEnv* env,
204 jobject jcaller,
205 jlong jurl_request_adapter,
206 jobject jchunk_byte_buffer,
207 jint jchunk_size,
208 jboolean jis_last_chunk) {
209 URLRequestAdapter* request_adapter =
210 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
211 DCHECK(jchunk_byte_buffer);
213 void* chunk = env->GetDirectBufferAddress(jchunk_byte_buffer);
214 request_adapter->AppendChunk(reinterpret_cast<const char*>(chunk),
215 jchunk_size, jis_last_chunk);
218 /* synchronized */
219 static void Start(JNIEnv* env, jobject jcaller, jlong jurl_request_adapter) {
220 URLRequestAdapter* request_adapter =
221 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
222 if (request_adapter != NULL)
223 request_adapter->Start();
226 /* synchronized */
227 static void DestroyRequestAdapter(JNIEnv* env,
228 jobject jcaller,
229 jlong jurl_request_adapter) {
230 URLRequestAdapter* request_adapter =
231 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
232 if (request_adapter != NULL)
233 request_adapter->Destroy();
236 /* synchronized */
237 static void Cancel(JNIEnv* env, jobject jcaller, jlong jurl_request_adapter) {
238 URLRequestAdapter* request_adapter =
239 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
240 if (request_adapter != NULL)
241 request_adapter->Cancel();
244 static jint GetErrorCode(JNIEnv* env,
245 jobject jcaller,
246 jlong jurl_request_adapter) {
247 URLRequestAdapter* request_adapter =
248 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
249 int error_code = request_adapter->error_code();
250 switch (error_code) {
251 // TODO(mef): Investigate returning success on positive values, too, as
252 // they technically indicate success.
253 case net::OK:
254 return REQUEST_ERROR_SUCCESS;
256 // TODO(mef): Investigate this. The fact is that Chrome does not do this,
257 // and this library is not just being used for downloads.
259 // Comment from src/content/browser/download/download_resource_handler.cc:
260 // ERR_CONTENT_LENGTH_MISMATCH and ERR_INCOMPLETE_CHUNKED_ENCODING are
261 // allowed since a number of servers in the wild close the connection too
262 // early by mistake. Other browsers - IE9, Firefox 11.0, and Safari 5.1.4 -
263 // treat downloads as complete in both cases, so we follow their lead.
264 case net::ERR_CONTENT_LENGTH_MISMATCH:
265 case net::ERR_INCOMPLETE_CHUNKED_ENCODING:
266 return REQUEST_ERROR_SUCCESS;
268 case net::ERR_INVALID_URL:
269 case net::ERR_DISALLOWED_URL_SCHEME:
270 case net::ERR_UNKNOWN_URL_SCHEME:
271 return REQUEST_ERROR_MALFORMED_URL;
273 case net::ERR_CONNECTION_TIMED_OUT:
274 return REQUEST_ERROR_CONNECTION_TIMED_OUT;
276 case net::ERR_NAME_NOT_RESOLVED:
277 return REQUEST_ERROR_UNKNOWN_HOST;
278 case net::ERR_TOO_MANY_REDIRECTS:
279 return REQUEST_ERROR_TOO_MANY_REDIRECTS;
281 return REQUEST_ERROR_UNKNOWN;
284 static jstring GetErrorString(JNIEnv* env,
285 jobject jcaller,
286 jlong jurl_request_adapter) {
287 URLRequestAdapter* request_adapter =
288 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
289 int error_code = request_adapter->error_code();
290 char buffer[200];
291 std::string error_string = net::ErrorToString(error_code);
292 snprintf(buffer,
293 sizeof(buffer),
294 "System error: %s(%d)",
295 error_string.c_str(),
296 error_code);
297 return ConvertUTF8ToJavaString(env, buffer).Release();
300 static jint GetHttpStatusCode(JNIEnv* env,
301 jobject jcaller,
302 jlong jurl_request_adapter) {
303 URLRequestAdapter* request_adapter =
304 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
305 return request_adapter->http_status_code();
308 static jstring GetHttpStatusText(JNIEnv* env,
309 jobject jcaller,
310 jlong jurl_request_adapter) {
311 URLRequestAdapter* request_adapter =
312 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
313 return ConvertUTF8ToJavaString(env, request_adapter->http_status_text())
314 .Release();
317 static jstring GetContentType(JNIEnv* env,
318 jobject jcaller,
319 jlong jurl_request_adapter) {
320 URLRequestAdapter* request_adapter =
321 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
322 if (request_adapter == NULL)
323 return NULL;
324 std::string type = request_adapter->content_type();
325 if (!type.empty()) {
326 return ConvertUTF8ToJavaString(env, type.c_str()).Release();
327 } else {
328 return NULL;
332 static jlong GetContentLength(JNIEnv* env,
333 jobject jcaller,
334 jlong jurl_request_adapter) {
335 URLRequestAdapter* request_adapter =
336 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
337 if (request_adapter == NULL)
338 return 0;
339 return request_adapter->content_length();
342 static jstring GetHeader(JNIEnv* env,
343 jobject jcaller,
344 jlong jurl_request_adapter,
345 jstring jheader_name) {
346 URLRequestAdapter* request_adapter =
347 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
348 if (request_adapter == NULL)
349 return NULL;
350 std::string header_name = ConvertJavaStringToUTF8(env, jheader_name);
351 std::string header_value = request_adapter->GetHeader(header_name);
352 if (!header_value.empty()) {
353 return ConvertUTF8ToJavaString(env, header_value.c_str()).Release();
354 } else {
355 return NULL;
359 static void GetAllHeaders(JNIEnv* env,
360 jobject jcaller,
361 jlong jurl_request_adapter,
362 jobject jheaders_map) {
363 URLRequestAdapter* request_adapter =
364 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
365 if (request_adapter == NULL)
366 return;
368 net::HttpResponseHeaders* headers = request_adapter->GetResponseHeaders();
369 if (headers == NULL)
370 return;
372 void* iter = NULL;
373 std::string header_name;
374 std::string header_value;
375 while (headers->EnumerateHeaderLines(&iter, &header_name, &header_value)) {
376 ScopedJavaLocalRef<jstring> name =
377 ConvertUTF8ToJavaString(env, header_name);
378 ScopedJavaLocalRef<jstring> value =
379 ConvertUTF8ToJavaString(env, header_value);
380 Java_ChromiumUrlRequest_onAppendResponseHeader(env, jcaller, jheaders_map,
381 name.obj(), value.obj());
384 // Some implementations (notably HttpURLConnection) include a mapping for the
385 // null key; in HTTP's case, this maps to the HTTP status line.
386 ScopedJavaLocalRef<jstring> status_line =
387 ConvertUTF8ToJavaString(env, headers->GetStatusLine());
388 Java_ChromiumUrlRequest_onAppendResponseHeader(env, jcaller, jheaders_map,
389 NULL, status_line.obj());
392 static jstring GetNegotiatedProtocol(JNIEnv* env,
393 jobject jcaller,
394 jlong jurl_request_adapter) {
395 URLRequestAdapter* request_adapter =
396 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
397 if (request_adapter == NULL)
398 return ConvertUTF8ToJavaString(env, "").Release();
400 std::string negotiated_protocol = request_adapter->GetNegotiatedProtocol();
401 return ConvertUTF8ToJavaString(env, negotiated_protocol.c_str()).Release();
404 static void DisableRedirects(JNIEnv* env, jobject jcaller,
405 jlong jrequest_adapter) {
406 URLRequestAdapter* request_adapter =
407 reinterpret_cast<URLRequestAdapter*>(jrequest_adapter);
408 if (request_adapter != NULL)
409 request_adapter->DisableRedirects();
412 } // namespace cronet