switch the lld bot to the new COFF linker, 2nd try
[chromium-blink-merge.git] / components / cronet / android / chromium_url_request.cc
blob140e4767253545e94f1c92ecafc817aa65f1c94e
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 std::string method_post("POST");
44 request_adapter->SetMethod(method_post);
46 std::string content_type_header("Content-Type");
47 std::string content_type_string(ConvertJavaStringToUTF8(env, content_type));
49 request_adapter->AddHeader(content_type_header, content_type_string);
52 // A delegate of URLRequestAdapter that delivers callbacks to the Java layer.
53 class JniURLRequestAdapterDelegate
54 : public URLRequestAdapter::URLRequestAdapterDelegate {
55 public:
56 JniURLRequestAdapterDelegate(JNIEnv* env, jobject owner) {
57 owner_ = env->NewGlobalRef(owner);
60 void OnResponseStarted(URLRequestAdapter* request_adapter) override {
61 JNIEnv* env = base::android::AttachCurrentThread();
62 cronet::Java_ChromiumUrlRequest_onResponseStarted(env, owner_);
65 void OnBytesRead(URLRequestAdapter* request_adapter,
66 int bytes_read) override {
67 if (bytes_read != 0) {
68 JNIEnv* env = base::android::AttachCurrentThread();
69 base::android::ScopedJavaLocalRef<jobject> java_buffer(
70 env, env->NewDirectByteBuffer(request_adapter->Data(), bytes_read));
71 cronet::Java_ChromiumUrlRequest_onBytesRead(
72 env, owner_, java_buffer.obj());
76 void OnRequestFinished(URLRequestAdapter* request_adapter) override {
77 JNIEnv* env = base::android::AttachCurrentThread();
78 cronet::Java_ChromiumUrlRequest_finish(env, owner_);
81 int ReadFromUploadChannel(net::IOBuffer* buf, int buf_length) override {
82 JNIEnv* env = base::android::AttachCurrentThread();
83 base::android::ScopedJavaLocalRef<jobject> java_buffer(
84 env, env->NewDirectByteBuffer(buf->data(), buf_length));
85 jint bytes_read = cronet::Java_ChromiumUrlRequest_readFromUploadChannel(
86 env, owner_, java_buffer.obj());
87 return bytes_read;
90 protected:
91 ~JniURLRequestAdapterDelegate() override {
92 JNIEnv* env = base::android::AttachCurrentThread();
93 env->DeleteGlobalRef(owner_);
96 private:
97 jobject owner_;
99 DISALLOW_COPY_AND_ASSIGN(JniURLRequestAdapterDelegate);
102 } // namespace
104 // Explicitly register static JNI functions.
105 bool ChromiumUrlRequestRegisterJni(JNIEnv* env) {
106 return RegisterNativesImpl(env);
109 static jlong CreateRequestAdapter(JNIEnv* env,
110 jobject jcaller,
111 jlong jurl_request_context_adapter,
112 jstring jurl,
113 jint jrequest_priority) {
114 URLRequestContextAdapter* context_adapter =
115 reinterpret_cast<URLRequestContextAdapter*>(jurl_request_context_adapter);
116 DCHECK(context_adapter);
118 GURL url(ConvertJavaStringToUTF8(env, jurl));
120 VLOG(1) << "New chromium network request: " << url.possibly_invalid_spec();
122 URLRequestAdapter* adapter = new URLRequestAdapter(
123 context_adapter, new JniURLRequestAdapterDelegate(env, jcaller), url,
124 ConvertRequestPriority(jrequest_priority));
126 return reinterpret_cast<jlong>(adapter);
129 // synchronized
130 static void AddHeader(JNIEnv* env,
131 jobject jcaller,
132 jlong jurl_request_adapter,
133 jstring jheader_name,
134 jstring jheader_value) {
135 URLRequestAdapter* request_adapter =
136 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
137 DCHECK(request_adapter);
139 std::string header_name(ConvertJavaStringToUTF8(env, jheader_name));
140 std::string header_value(ConvertJavaStringToUTF8(env, jheader_value));
142 request_adapter->AddHeader(header_name, header_value);
145 static void SetMethod(JNIEnv* env,
146 jobject jcaller,
147 jlong jurl_request_adapter,
148 jstring jmethod) {
149 URLRequestAdapter* request_adapter =
150 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
151 DCHECK(request_adapter);
153 std::string method(ConvertJavaStringToUTF8(env, jmethod));
155 request_adapter->SetMethod(method);
158 static void SetUploadData(JNIEnv* env,
159 jobject jcaller,
160 jlong jurl_request_adapter,
161 jstring jcontent_type,
162 jbyteArray jcontent) {
163 URLRequestAdapter* request_adapter =
164 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
165 DCHECK(request_adapter);
166 SetPostContentType(env, request_adapter, jcontent_type);
168 if (jcontent != NULL) {
169 jsize size = env->GetArrayLength(jcontent);
170 if (size > 0) {
171 jbyte* content_bytes = env->GetByteArrayElements(jcontent, NULL);
172 request_adapter->SetUploadContent(
173 reinterpret_cast<const char*>(content_bytes), size);
174 env->ReleaseByteArrayElements(jcontent, content_bytes, 0);
179 static void SetUploadChannel(JNIEnv* env,
180 jobject jcaller,
181 jlong jurl_request_adapter,
182 jstring jcontent_type,
183 jlong jcontent_length) {
184 URLRequestAdapter* request_adapter =
185 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
186 DCHECK(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 DCHECK(request_adapter);
199 SetPostContentType(env, request_adapter, jcontent_type);
201 request_adapter->EnableChunkedUpload();
204 static void AppendChunk(JNIEnv* env,
205 jobject jcaller,
206 jlong jurl_request_adapter,
207 jobject jchunk_byte_buffer,
208 jint jchunk_size,
209 jboolean jis_last_chunk) {
210 URLRequestAdapter* request_adapter =
211 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
212 DCHECK(request_adapter);
213 DCHECK(jchunk_byte_buffer);
215 void* chunk = env->GetDirectBufferAddress(jchunk_byte_buffer);
216 request_adapter->AppendChunk(reinterpret_cast<const char*>(chunk),
217 jchunk_size, jis_last_chunk);
220 /* synchronized */
221 static void Start(JNIEnv* env, jobject jcaller, jlong jurl_request_adapter) {
222 URLRequestAdapter* request_adapter =
223 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
224 if (request_adapter != NULL)
225 request_adapter->Start();
228 /* synchronized */
229 static void DestroyRequestAdapter(JNIEnv* env,
230 jobject jcaller,
231 jlong jurl_request_adapter) {
232 URLRequestAdapter* request_adapter =
233 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
234 if (request_adapter != NULL)
235 request_adapter->Destroy();
238 /* synchronized */
239 static void Cancel(JNIEnv* env, jobject jcaller, jlong jurl_request_adapter) {
240 URLRequestAdapter* request_adapter =
241 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
242 if (request_adapter != NULL)
243 request_adapter->Cancel();
246 static jint GetErrorCode(JNIEnv* env,
247 jobject jcaller,
248 jlong jurl_request_adapter) {
249 URLRequestAdapter* request_adapter =
250 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
251 DCHECK(request_adapter);
252 int error_code = request_adapter->error_code();
253 switch (error_code) {
254 // TODO(mef): Investigate returning success on positive values, too, as
255 // they technically indicate success.
256 case net::OK:
257 return REQUEST_ERROR_SUCCESS;
259 // TODO(mef): Investigate this. The fact is that Chrome does not do this,
260 // and this library is not just being used for downloads.
262 // Comment from src/content/browser/download/download_resource_handler.cc:
263 // ERR_CONTENT_LENGTH_MISMATCH and ERR_INCOMPLETE_CHUNKED_ENCODING are
264 // allowed since a number of servers in the wild close the connection too
265 // early by mistake. Other browsers - IE9, Firefox 11.0, and Safari 5.1.4 -
266 // treat downloads as complete in both cases, so we follow their lead.
267 case net::ERR_CONTENT_LENGTH_MISMATCH:
268 case net::ERR_INCOMPLETE_CHUNKED_ENCODING:
269 return REQUEST_ERROR_SUCCESS;
271 case net::ERR_INVALID_URL:
272 case net::ERR_DISALLOWED_URL_SCHEME:
273 case net::ERR_UNKNOWN_URL_SCHEME:
274 return REQUEST_ERROR_MALFORMED_URL;
276 case net::ERR_CONNECTION_TIMED_OUT:
277 return REQUEST_ERROR_CONNECTION_TIMED_OUT;
279 case net::ERR_NAME_NOT_RESOLVED:
280 return REQUEST_ERROR_UNKNOWN_HOST;
281 case net::ERR_TOO_MANY_REDIRECTS:
282 return REQUEST_ERROR_TOO_MANY_REDIRECTS;
284 return REQUEST_ERROR_UNKNOWN;
287 static jstring GetErrorString(JNIEnv* env,
288 jobject jcaller,
289 jlong jurl_request_adapter) {
290 URLRequestAdapter* request_adapter =
291 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
292 DCHECK(request_adapter);
293 int error_code = request_adapter->error_code();
294 char buffer[200];
295 std::string error_string = net::ErrorToString(error_code);
296 snprintf(buffer,
297 sizeof(buffer),
298 "System error: %s(%d)",
299 error_string.c_str(),
300 error_code);
301 return ConvertUTF8ToJavaString(env, buffer).Release();
304 static jint GetHttpStatusCode(JNIEnv* env,
305 jobject jcaller,
306 jlong jurl_request_adapter) {
307 URLRequestAdapter* request_adapter =
308 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
309 DCHECK(request_adapter);
310 return request_adapter->http_status_code();
313 static jstring GetHttpStatusText(JNIEnv* env,
314 jobject jcaller,
315 jlong jurl_request_adapter) {
316 URLRequestAdapter* request_adapter =
317 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
318 DCHECK(request_adapter);
319 return ConvertUTF8ToJavaString(env, request_adapter->http_status_text())
320 .Release();
323 static jstring GetContentType(JNIEnv* env,
324 jobject jcaller,
325 jlong jurl_request_adapter) {
326 URLRequestAdapter* request_adapter =
327 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
328 DCHECK(request_adapter);
329 std::string type = request_adapter->content_type();
330 if (!type.empty()) {
331 return ConvertUTF8ToJavaString(env, type.c_str()).Release();
332 } else {
333 return NULL;
337 static jlong GetContentLength(JNIEnv* env,
338 jobject jcaller,
339 jlong jurl_request_adapter) {
340 URLRequestAdapter* request_adapter =
341 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
342 DCHECK(request_adapter);
343 return request_adapter->content_length();
346 static jstring GetHeader(JNIEnv* env,
347 jobject jcaller,
348 jlong jurl_request_adapter,
349 jstring jheader_name) {
350 URLRequestAdapter* request_adapter =
351 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
352 DCHECK(request_adapter);
353 std::string header_name = ConvertJavaStringToUTF8(env, jheader_name);
354 std::string header_value = request_adapter->GetHeader(header_name);
355 if (!header_value.empty())
356 return ConvertUTF8ToJavaString(env, header_value.c_str()).Release();
357 return NULL;
360 static void GetAllHeaders(JNIEnv* env,
361 jobject jcaller,
362 jlong jurl_request_adapter,
363 jobject jheaders_map) {
364 URLRequestAdapter* request_adapter =
365 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
366 DCHECK(request_adapter);
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 DCHECK(request_adapter);
399 std::string negotiated_protocol = request_adapter->GetNegotiatedProtocol();
400 return ConvertUTF8ToJavaString(env, negotiated_protocol.c_str()).Release();
403 static jboolean GetWasCached(JNIEnv* env,
404 jobject jcaller,
405 jlong jurl_request_adapter) {
406 URLRequestAdapter* request_adapter =
407 reinterpret_cast<URLRequestAdapter*>(jurl_request_adapter);
408 DCHECK(request_adapter);
410 bool was_cached = request_adapter->GetWasCached();
411 return was_cached ? JNI_TRUE : JNI_FALSE;
414 static void DisableRedirects(JNIEnv* env, jobject jcaller,
415 jlong jrequest_adapter) {
416 URLRequestAdapter* request_adapter =
417 reinterpret_cast<URLRequestAdapter*>(jrequest_adapter);
418 DCHECK(request_adapter);
419 request_adapter->DisableRedirects();
422 } // namespace cronet