Ignore title parameter for navigator.registerProtocolHandler
[chromium-blink-merge.git] / components / cronet / android / org_chromium_net_UrlRequest.cc
blob7d3cf6ba6eb970854d055a023df74c5547295564
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_context_peer.h"
11 #include "components/cronet/android/url_request_peer.h"
12 #include "jni/UrlRequest_jni.h"
13 #include "net/base/net_errors.h"
14 #include "net/base/request_priority.h"
16 using base::android::ConvertUTF8ToJavaString;
18 namespace cronet {
19 namespace {
21 net::RequestPriority ConvertRequestPriority(jint request_priority) {
22 switch (request_priority) {
23 case REQUEST_PRIORITY_IDLE:
24 return net::IDLE;
25 case REQUEST_PRIORITY_LOWEST:
26 return net::LOWEST;
27 case REQUEST_PRIORITY_LOW:
28 return net::LOW;
29 case REQUEST_PRIORITY_MEDIUM:
30 return net::MEDIUM;
31 case REQUEST_PRIORITY_HIGHEST:
32 return net::HIGHEST;
33 default:
34 return net::LOWEST;
38 void SetPostContentType(JNIEnv* env,
39 URLRequestPeer* request,
40 jstring content_type) {
41 DCHECK(request != NULL);
43 std::string method_post("POST");
44 request->SetMethod(method_post);
46 std::string content_type_header("Content-Type");
48 const char* content_type_utf8 = env->GetStringUTFChars(content_type, NULL);
49 std::string content_type_string(content_type_utf8);
50 env->ReleaseStringUTFChars(content_type, content_type_utf8);
52 request->AddHeader(content_type_header, content_type_string);
55 // A delegate of URLRequestPeer that delivers callbacks to the Java layer.
56 class JniURLRequestPeerDelegate
57 : public URLRequestPeer::URLRequestPeerDelegate {
58 public:
59 JniURLRequestPeerDelegate(JNIEnv* env, jobject owner) {
60 owner_ = env->NewGlobalRef(owner);
63 virtual void OnAppendChunkCompleted(URLRequestPeer* request) OVERRIDE {
64 JNIEnv* env = base::android::AttachCurrentThread();
65 cronet::Java_UrlRequest_onAppendChunkCompleted(env, owner_);
68 virtual void OnResponseStarted(URLRequestPeer* request) OVERRIDE {
69 JNIEnv* env = base::android::AttachCurrentThread();
70 cronet::Java_UrlRequest_onResponseStarted(env, owner_);
73 virtual void OnBytesRead(URLRequestPeer* request) OVERRIDE {
74 int bytes_read = request->bytes_read();
75 if (bytes_read != 0) {
76 JNIEnv* env = base::android::AttachCurrentThread();
77 jobject bytebuf = env->NewDirectByteBuffer(request->Data(), bytes_read);
78 cronet::Java_UrlRequest_onBytesRead(env, owner_, bytebuf);
79 env->DeleteLocalRef(bytebuf);
83 virtual void OnRequestFinished(URLRequestPeer* request) OVERRIDE {
84 JNIEnv* env = base::android::AttachCurrentThread();
85 cronet::Java_UrlRequest_finish(env, owner_);
88 protected:
89 virtual ~JniURLRequestPeerDelegate() {
90 JNIEnv* env = base::android::AttachCurrentThread();
91 env->DeleteGlobalRef(owner_);
94 private:
95 jobject owner_;
97 DISALLOW_COPY_AND_ASSIGN(JniURLRequestPeerDelegate);
100 } // namespace
102 // Explicitly register static JNI functions.
103 bool UrlRequestRegisterJni(JNIEnv* env) { return RegisterNativesImpl(env); }
105 static jlong CreateRequestPeer(JNIEnv* env,
106 jobject object,
107 jlong urlRequestContextPeer,
108 jstring url_string,
109 jint priority) {
110 URLRequestContextPeer* context =
111 reinterpret_cast<URLRequestContextPeer*>(urlRequestContextPeer);
112 DCHECK(context != NULL);
114 const char* url_utf8 = env->GetStringUTFChars(url_string, NULL);
116 DVLOG(context->logging_level())
117 << "New chromium network request. URL:" << url_utf8;
119 GURL url(url_utf8);
121 env->ReleaseStringUTFChars(url_string, url_utf8);
123 URLRequestPeer* peer =
124 new URLRequestPeer(context,
125 new JniURLRequestPeerDelegate(env, object),
126 url,
127 ConvertRequestPriority(priority));
129 return reinterpret_cast<jlong>(peer);
132 // synchronized
133 static void AddHeader(JNIEnv* env,
134 jobject object,
135 jlong urlRequestPeer,
136 jstring name,
137 jstring value) {
138 URLRequestPeer* request = reinterpret_cast<URLRequestPeer*>(urlRequestPeer);
139 DCHECK(request != NULL);
141 const char* name_utf8 = env->GetStringUTFChars(name, NULL);
142 std::string name_string(name_utf8);
143 env->ReleaseStringUTFChars(name, name_utf8);
145 const char* value_utf8 = env->GetStringUTFChars(value, NULL);
146 std::string value_string(value_utf8);
147 env->ReleaseStringUTFChars(value, value_utf8);
149 request->AddHeader(name_string, value_string);
152 static void SetPostData(JNIEnv* env,
153 jobject object,
154 jlong urlRequestPeer,
155 jstring content_type,
156 jbyteArray content) {
157 URLRequestPeer* request = reinterpret_cast<URLRequestPeer*>(urlRequestPeer);
158 SetPostContentType(env, request, content_type);
160 if (content != NULL) {
161 jsize size = env->GetArrayLength(content);
162 if (size > 0) {
163 jbyte* content_bytes = env->GetByteArrayElements(content, NULL);
164 request->SetPostContent(reinterpret_cast<const char*>(content_bytes),
165 size);
166 env->ReleaseByteArrayElements(content, content_bytes, 0);
171 static void BeginChunkedUpload(JNIEnv* env,
172 jobject object,
173 jlong urlRequestPeer,
174 jstring content_type) {
175 URLRequestPeer* request = reinterpret_cast<URLRequestPeer*>(urlRequestPeer);
176 SetPostContentType(env, request, content_type);
178 request->EnableStreamingUpload();
181 static void AppendChunk(JNIEnv* env,
182 jobject object,
183 jlong urlRequestPeer,
184 jobject chunk_byte_buffer,
185 jint chunk_size,
186 jboolean is_last_chunk) {
187 URLRequestPeer* request = reinterpret_cast<URLRequestPeer*>(urlRequestPeer);
188 CHECK(request != NULL);
190 if (chunk_byte_buffer != NULL) {
191 void* chunk = env->GetDirectBufferAddress(chunk_byte_buffer);
192 request->AppendChunk(
193 reinterpret_cast<const char*>(chunk), chunk_size, is_last_chunk);
197 /* synchronized */
198 static void Start(JNIEnv* env, jobject object, jlong urlRequestPeer) {
199 URLRequestPeer* request = reinterpret_cast<URLRequestPeer*>(urlRequestPeer);
200 if (request != NULL) {
201 request->Start();
205 /* synchronized */
206 static void DestroyRequestPeer(JNIEnv* env,
207 jobject object,
208 jlong urlRequestPeer) {
209 URLRequestPeer* request = reinterpret_cast<URLRequestPeer*>(urlRequestPeer);
210 if (request != NULL) {
211 request->Destroy();
215 /* synchronized */
216 static void Cancel(JNIEnv* env, jobject object, jlong urlRequestPeer) {
217 URLRequestPeer* request = reinterpret_cast<URLRequestPeer*>(urlRequestPeer);
218 if (request != NULL) {
219 request->Cancel();
223 static jint GetErrorCode(JNIEnv* env, jobject object, jlong urlRequestPeer) {
224 URLRequestPeer* request = reinterpret_cast<URLRequestPeer*>(urlRequestPeer);
225 int error_code = request->error_code();
226 switch (error_code) {
227 // TODO(mef): Investigate returning success on positive values, too, as
228 // they technically indicate success.
229 case net::OK:
230 return REQUEST_ERROR_SUCCESS;
232 // TODO(mef): Investigate this. The fact is that Chrome does not do this,
233 // and this library is not just being used for downloads.
235 // Comment from src/content/browser/download/download_resource_handler.cc:
236 // ERR_CONTENT_LENGTH_MISMATCH and ERR_INCOMPLETE_CHUNKED_ENCODING are
237 // allowed since a number of servers in the wild close the connection too
238 // early by mistake. Other browsers - IE9, Firefox 11.0, and Safari 5.1.4 -
239 // treat downloads as complete in both cases, so we follow their lead.
240 case net::ERR_CONTENT_LENGTH_MISMATCH:
241 case net::ERR_INCOMPLETE_CHUNKED_ENCODING:
242 return REQUEST_ERROR_SUCCESS;
244 case net::ERR_INVALID_URL:
245 case net::ERR_DISALLOWED_URL_SCHEME:
246 case net::ERR_UNKNOWN_URL_SCHEME:
247 return REQUEST_ERROR_MALFORMED_URL;
249 case net::ERR_CONNECTION_TIMED_OUT:
250 return REQUEST_ERROR_CONNECTION_TIMED_OUT;
252 case net::ERR_NAME_NOT_RESOLVED:
253 return REQUEST_ERROR_UNKNOWN_HOST;
255 return REQUEST_ERROR_UNKNOWN;
258 static jstring GetErrorString(JNIEnv* env,
259 jobject object,
260 jlong urlRequestPeer) {
261 URLRequestPeer* request = reinterpret_cast<URLRequestPeer*>(urlRequestPeer);
262 int error_code = request->error_code();
263 char buffer[200];
264 snprintf(buffer,
265 sizeof(buffer),
266 "System error: %s(%d)",
267 net::ErrorToString(error_code),
268 error_code);
269 return ConvertUTF8ToJavaString(env, buffer).Release();
272 static jint GetHttpStatusCode(JNIEnv* env,
273 jobject object,
274 jlong urlRequestPeer) {
275 URLRequestPeer* request = reinterpret_cast<URLRequestPeer*>(urlRequestPeer);
276 return request->http_status_code();
279 static jstring GetContentType(JNIEnv* env,
280 jobject object,
281 jlong urlRequestPeer) {
282 URLRequestPeer* request = reinterpret_cast<URLRequestPeer*>(urlRequestPeer);
283 if (request == NULL) {
284 return NULL;
286 std::string type = request->content_type();
287 if (!type.empty()) {
288 return ConvertUTF8ToJavaString(env, type.c_str()).Release();
289 } else {
290 return NULL;
294 static jlong GetContentLength(JNIEnv* env,
295 jobject object,
296 jlong urlRequestPeer) {
297 URLRequestPeer* request = reinterpret_cast<URLRequestPeer*>(urlRequestPeer);
298 if (request == NULL) {
299 return 0;
301 return request->content_length();
304 } // namespace cronet