Rename url_request_[context_]peer.* into url_request_[context_]adapter.*
[chromium-blink-merge.git] / components / cronet / android / org_chromium_net_UrlRequest.cc
blobe38f93fcd35cabe0f45fba5e52b30ac4b031a3d4
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/org_chromium_net_UrlRequest.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/UrlRequest_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;
19 namespace cronet {
20 namespace {
22 net::RequestPriority ConvertRequestPriority(jint request_priority) {
23 switch (request_priority) {
24 case REQUEST_PRIORITY_IDLE:
25 return net::IDLE;
26 case REQUEST_PRIORITY_LOWEST:
27 return net::LOWEST;
28 case REQUEST_PRIORITY_LOW:
29 return net::LOW;
30 case REQUEST_PRIORITY_MEDIUM:
31 return net::MEDIUM;
32 case REQUEST_PRIORITY_HIGHEST:
33 return net::HIGHEST;
34 default:
35 return net::LOWEST;
39 void SetPostContentType(JNIEnv* env,
40 URLRequestAdapter* request,
41 jstring content_type) {
42 DCHECK(request != NULL);
44 std::string method_post("POST");
45 request->SetMethod(method_post);
47 std::string content_type_header("Content-Type");
49 const char* content_type_utf8 = env->GetStringUTFChars(content_type, NULL);
50 std::string content_type_string(content_type_utf8);
51 env->ReleaseStringUTFChars(content_type, content_type_utf8);
53 request->AddHeader(content_type_header, content_type_string);
56 // A delegate of URLRequestAdapter that delivers callbacks to the Java layer.
57 class JniURLRequestAdapterDelegate
58 : public URLRequestAdapter::URLRequestAdapterDelegate {
59 public:
60 JniURLRequestAdapterDelegate(JNIEnv* env, jobject owner) {
61 owner_ = env->NewGlobalRef(owner);
64 virtual void OnResponseStarted(URLRequestAdapter* request) OVERRIDE {
65 JNIEnv* env = base::android::AttachCurrentThread();
66 cronet::Java_UrlRequest_onResponseStarted(env, owner_);
69 virtual void OnBytesRead(URLRequestAdapter* request) OVERRIDE {
70 int bytes_read = request->bytes_read();
71 if (bytes_read != 0) {
72 JNIEnv* env = base::android::AttachCurrentThread();
73 base::android::ScopedJavaLocalRef<jobject> java_buffer(
74 env, env->NewDirectByteBuffer(request->Data(), bytes_read));
75 cronet::Java_UrlRequest_onBytesRead(env, owner_, java_buffer.obj());
79 virtual void OnRequestFinished(URLRequestAdapter* request) OVERRIDE {
80 JNIEnv* env = base::android::AttachCurrentThread();
81 cronet::Java_UrlRequest_finish(env, owner_);
84 virtual int ReadFromUploadChannel(net::IOBuffer* buf,
85 int buf_length) OVERRIDE {
86 JNIEnv* env = base::android::AttachCurrentThread();
87 base::android::ScopedJavaLocalRef<jobject> java_buffer(
88 env, env->NewDirectByteBuffer(buf->data(), buf_length));
89 jint bytes_read = cronet::Java_UrlRequest_readFromUploadChannel(
90 env, owner_, java_buffer.obj());
91 return bytes_read;
94 protected:
95 virtual ~JniURLRequestAdapterDelegate() {
96 JNIEnv* env = base::android::AttachCurrentThread();
97 env->DeleteGlobalRef(owner_);
100 private:
101 jobject owner_;
103 DISALLOW_COPY_AND_ASSIGN(JniURLRequestAdapterDelegate);
106 } // namespace
108 // Explicitly register static JNI functions.
109 bool UrlRequestRegisterJni(JNIEnv* env) { return RegisterNativesImpl(env); }
111 static jlong CreateRequestAdapter(JNIEnv* env,
112 jobject object,
113 jlong urlRequestContextAdapter,
114 jstring url_string,
115 jint priority) {
116 URLRequestContextAdapter* context =
117 reinterpret_cast<URLRequestContextAdapter*>(urlRequestContextAdapter);
118 DCHECK(context != NULL);
120 const char* url_utf8 = env->GetStringUTFChars(url_string, NULL);
122 VLOG(1) << "New chromium network request. URL:" << url_utf8;
124 GURL url(url_utf8);
126 env->ReleaseStringUTFChars(url_string, url_utf8);
128 URLRequestAdapter* adapter =
129 new URLRequestAdapter(context,
130 new JniURLRequestAdapterDelegate(env, object),
131 url,
132 ConvertRequestPriority(priority));
134 return reinterpret_cast<jlong>(adapter);
137 // synchronized
138 static void AddHeader(JNIEnv* env,
139 jobject object,
140 jlong urlRequestAdapter,
141 jstring name,
142 jstring value) {
143 URLRequestAdapter* request =
144 reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
145 DCHECK(request);
147 std::string name_string(base::android::ConvertJavaStringToUTF8(env, name));
148 std::string value_string(base::android::ConvertJavaStringToUTF8(env, value));
150 request->AddHeader(name_string, value_string);
153 static void SetMethod(JNIEnv* env,
154 jobject object,
155 jlong urlRequestAdapter,
156 jstring method) {
157 URLRequestAdapter* request =
158 reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
159 DCHECK(request);
161 std::string method_string(
162 base::android::ConvertJavaStringToUTF8(env, method));
164 request->SetMethod(method_string);
167 static void SetUploadData(JNIEnv* env,
168 jobject object,
169 jlong urlRequestAdapter,
170 jstring content_type,
171 jbyteArray content) {
172 URLRequestAdapter* request =
173 reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
174 SetPostContentType(env, request, content_type);
176 if (content != NULL) {
177 jsize size = env->GetArrayLength(content);
178 if (size > 0) {
179 jbyte* content_bytes = env->GetByteArrayElements(content, NULL);
180 request->SetUploadContent(reinterpret_cast<const char*>(content_bytes),
181 size);
182 env->ReleaseByteArrayElements(content, content_bytes, 0);
187 static void SetUploadChannel(JNIEnv* env,
188 jobject object,
189 jlong urlRequestAdapter,
190 jstring content_type,
191 jlong content_length) {
192 URLRequestAdapter* request =
193 reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
194 SetPostContentType(env, request, content_type);
196 request->SetUploadChannel(env, content_length);
200 /* synchronized */
201 static void Start(JNIEnv* env, jobject object, jlong urlRequestAdapter) {
202 URLRequestAdapter* request =
203 reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
204 if (request != NULL) {
205 request->Start();
209 /* synchronized */
210 static void DestroyRequestAdapter(JNIEnv* env,
211 jobject object,
212 jlong urlRequestAdapter) {
213 URLRequestAdapter* request =
214 reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
215 if (request != NULL) {
216 request->Destroy();
220 /* synchronized */
221 static void Cancel(JNIEnv* env, jobject object, jlong urlRequestAdapter) {
222 URLRequestAdapter* request =
223 reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
224 if (request != NULL) {
225 request->Cancel();
229 static jint GetErrorCode(JNIEnv* env, jobject object, jlong urlRequestAdapter) {
230 URLRequestAdapter* request =
231 reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
232 int error_code = request->error_code();
233 switch (error_code) {
234 // TODO(mef): Investigate returning success on positive values, too, as
235 // they technically indicate success.
236 case net::OK:
237 return REQUEST_ERROR_SUCCESS;
239 // TODO(mef): Investigate this. The fact is that Chrome does not do this,
240 // and this library is not just being used for downloads.
242 // Comment from src/content/browser/download/download_resource_handler.cc:
243 // ERR_CONTENT_LENGTH_MISMATCH and ERR_INCOMPLETE_CHUNKED_ENCODING are
244 // allowed since a number of servers in the wild close the connection too
245 // early by mistake. Other browsers - IE9, Firefox 11.0, and Safari 5.1.4 -
246 // treat downloads as complete in both cases, so we follow their lead.
247 case net::ERR_CONTENT_LENGTH_MISMATCH:
248 case net::ERR_INCOMPLETE_CHUNKED_ENCODING:
249 return REQUEST_ERROR_SUCCESS;
251 case net::ERR_INVALID_URL:
252 case net::ERR_DISALLOWED_URL_SCHEME:
253 case net::ERR_UNKNOWN_URL_SCHEME:
254 return REQUEST_ERROR_MALFORMED_URL;
256 case net::ERR_CONNECTION_TIMED_OUT:
257 return REQUEST_ERROR_CONNECTION_TIMED_OUT;
259 case net::ERR_NAME_NOT_RESOLVED:
260 return REQUEST_ERROR_UNKNOWN_HOST;
262 return REQUEST_ERROR_UNKNOWN;
265 static jstring GetErrorString(JNIEnv* env,
266 jobject object,
267 jlong urlRequestAdapter) {
268 URLRequestAdapter* request =
269 reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
270 int error_code = request->error_code();
271 char buffer[200];
272 std::string error_string = net::ErrorToString(error_code);
273 snprintf(buffer,
274 sizeof(buffer),
275 "System error: %s(%d)",
276 error_string.c_str(),
277 error_code);
278 return ConvertUTF8ToJavaString(env, buffer).Release();
281 static jint GetHttpStatusCode(JNIEnv* env,
282 jobject object,
283 jlong urlRequestAdapter) {
284 URLRequestAdapter* request =
285 reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
286 return request->http_status_code();
289 static jstring GetContentType(JNIEnv* env,
290 jobject object,
291 jlong urlRequestAdapter) {
292 URLRequestAdapter* request =
293 reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
294 if (request == NULL) {
295 return NULL;
297 std::string type = request->content_type();
298 if (!type.empty()) {
299 return ConvertUTF8ToJavaString(env, type.c_str()).Release();
300 } else {
301 return NULL;
305 static jlong GetContentLength(JNIEnv* env,
306 jobject object,
307 jlong urlRequestAdapter) {
308 URLRequestAdapter* request =
309 reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
310 if (request == NULL) {
311 return 0;
313 return request->content_length();
316 static jstring GetHeader(JNIEnv* env,
317 jobject object,
318 jlong urlRequestAdapter,
319 jstring name) {
320 URLRequestAdapter* request =
321 reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
322 if (request == NULL) {
323 return NULL;
326 std::string name_string = base::android::ConvertJavaStringToUTF8(env, name);
327 std::string value = request->GetHeader(name_string);
328 if (!value.empty()) {
329 return ConvertUTF8ToJavaString(env, value.c_str()).Release();
330 } else {
331 return NULL;
335 static void GetAllHeaders(JNIEnv* env,
336 jobject object,
337 jlong urlRequestAdapter,
338 jobject headersMap) {
339 URLRequestAdapter* request =
340 reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
341 if (request == NULL)
342 return;
344 net::HttpResponseHeaders* headers = request->GetResponseHeaders();
345 if (headers == NULL)
346 return;
348 void* iter = NULL;
349 std::string header_name;
350 std::string header_value;
351 while (headers->EnumerateHeaderLines(&iter, &header_name, &header_value)) {
352 ScopedJavaLocalRef<jstring> name =
353 ConvertUTF8ToJavaString(env, header_name);
354 ScopedJavaLocalRef<jstring> value =
355 ConvertUTF8ToJavaString(env, header_value);
356 Java_UrlRequest_onAppendResponseHeader(
357 env, object, headersMap, name.Release(), value.Release());
360 // Some implementations (notably HttpURLConnection) include a mapping for the
361 // null key; in HTTP's case, this maps to the HTTP status line.
362 ScopedJavaLocalRef<jstring> status_line =
363 ConvertUTF8ToJavaString(env, headers->GetStatusLine());
364 Java_UrlRequest_onAppendResponseHeader(
365 env, object, headersMap, NULL, status_line.Release());
368 } // namespace cronet