1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// found in the LICENSE file.
4c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/cronet/android/chromium_url_request.h"
6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
7c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/android/jni_android.h"
8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/android/jni_string.h"
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/macros.h"
106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/cronet/android/url_request_adapter.h"
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/cronet/android/url_request_context_adapter.h"
126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "jni/ChromiumUrlRequest_jni.h"
13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "net/base/net_errors.h"
14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "net/base/request_priority.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/http/http_response_headers.h"
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)using base::android::ConvertUTF8ToJavaString;
18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace cronet {
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace {
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnet::RequestPriority ConvertRequestPriority(jint request_priority) {
23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  switch (request_priority) {
24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case REQUEST_PRIORITY_IDLE:
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return net::IDLE;
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case REQUEST_PRIORITY_LOWEST:
27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return net::LOWEST;
28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case REQUEST_PRIORITY_LOW:
29c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return net::LOW;
30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case REQUEST_PRIORITY_MEDIUM:
31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return net::MEDIUM;
32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case REQUEST_PRIORITY_HIGHEST:
33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return net::HIGHEST;
34c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    default:
35c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return net::LOWEST;
36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid SetPostContentType(JNIEnv* env,
406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                        URLRequestAdapter* request,
41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                        jstring content_type) {
42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(request != NULL);
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::string method_post("POST");
45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  request->SetMethod(method_post);
46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::string content_type_header("Content-Type");
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string content_type_string(
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::android::ConvertJavaStringToUTF8(env, content_type));
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  request->AddHeader(content_type_header, content_type_string);
52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// A delegate of URLRequestAdapter that delivers callbacks to the Java layer.
556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class JniURLRequestAdapterDelegate
566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    : public URLRequestAdapter::URLRequestAdapterDelegate {
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public:
586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  JniURLRequestAdapterDelegate(JNIEnv* env, jobject owner) {
59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    owner_ = env->NewGlobalRef(owner);
60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual void OnResponseStarted(URLRequestAdapter* request) OVERRIDE {
63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    JNIEnv* env = base::android::AttachCurrentThread();
646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    cronet::Java_ChromiumUrlRequest_onResponseStarted(env, owner_);
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual void OnBytesRead(URLRequestAdapter* request) OVERRIDE {
68c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int bytes_read = request->bytes_read();
69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (bytes_read != 0) {
70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      JNIEnv* env = base::android::AttachCurrentThread();
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::android::ScopedJavaLocalRef<jobject> java_buffer(
726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          env, env->NewDirectByteBuffer(request->Data(), bytes_read));
736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      cronet::Java_ChromiumUrlRequest_onBytesRead(
746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          env, owner_, java_buffer.obj());
75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual void OnRequestFinished(URLRequestAdapter* request) OVERRIDE {
79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    JNIEnv* env = base::android::AttachCurrentThread();
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    cronet::Java_ChromiumUrlRequest_finish(env, owner_);
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual int ReadFromUploadChannel(net::IOBuffer* buf,
846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                    int buf_length) OVERRIDE {
856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    JNIEnv* env = base::android::AttachCurrentThread();
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    base::android::ScopedJavaLocalRef<jobject> java_buffer(
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        env, env->NewDirectByteBuffer(buf->data(), buf_length));
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    jint bytes_read = cronet::Java_ChromiumUrlRequest_readFromUploadChannel(
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        env, owner_, java_buffer.obj());
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return bytes_read;
91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
92c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch protected:
946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual ~JniURLRequestAdapterDelegate() {
95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    JNIEnv* env = base::android::AttachCurrentThread();
96c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    env->DeleteGlobalRef(owner_);
97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch private:
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  jobject owner_;
101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(JniURLRequestAdapterDelegate);
103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace
106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Explicitly register static JNI functions.
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool ChromiumUrlRequestRegisterJni(JNIEnv* env) {
1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return RegisterNativesImpl(env);
1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static jlong CreateRequestAdapter(JNIEnv* env,
1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                  jobject object,
1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                  jlong urlRequestContextAdapter,
1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                  jstring url_string,
1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                  jint priority) {
1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestContextAdapter* context =
1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestContextAdapter*>(urlRequestContextAdapter);
119c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(context != NULL);
120c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GURL url(base::android::ConvertJavaStringToUTF8(env, url_string));
122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VLOG(1) << "New chromium network request: " << url.possibly_invalid_spec();
124c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* adapter =
1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      new URLRequestAdapter(context,
1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                            new JniURLRequestAdapterDelegate(env, object),
1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                            url,
1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                            ConvertRequestPriority(priority));
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return reinterpret_cast<jlong>(adapter);
132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
133c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// synchronized
135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic void AddHeader(JNIEnv* env,
136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                      jobject object,
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                      jlong urlRequestAdapter,
138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                      jstring name,
139c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                      jstring value) {
1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* request =
1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(request);
143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string name_string(base::android::ConvertJavaStringToUTF8(env, name));
145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string value_string(base::android::ConvertJavaStringToUTF8(env, value));
146c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  request->AddHeader(name_string, value_string);
148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
150116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic void SetMethod(JNIEnv* env,
151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                      jobject object,
1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                      jlong urlRequestAdapter,
153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                      jstring method) {
1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* request =
1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(request);
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string method_string(
159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::android::ConvertJavaStringToUTF8(env, method));
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  request->SetMethod(method_string);
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic void SetUploadData(JNIEnv* env,
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          jobject object,
1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                          jlong urlRequestAdapter,
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          jstring content_type,
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          jbyteArray content) {
1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* request =
1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
171c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetPostContentType(env, request, content_type);
172c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (content != NULL) {
174c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    jsize size = env->GetArrayLength(content);
175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (size > 0) {
176c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      jbyte* content_bytes = env->GetByteArrayElements(content, NULL);
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      request->SetUploadContent(reinterpret_cast<const char*>(content_bytes),
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                size);
179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      env->ReleaseByteArrayElements(content, content_bytes, 0);
180c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
181c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
183c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
184116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic void SetUploadChannel(JNIEnv* env,
185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                             jobject object,
1866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                             jlong urlRequestAdapter,
187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                             jstring content_type,
188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                             jlong content_length) {
1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* request =
1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetPostContentType(env, request, content_type);
192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  request->SetUploadChannel(env, content_length);
194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
19603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)static void EnableChunkedUpload(JNIEnv* env,
19703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                               jobject object,
19803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                               jlong urlRequestAdapter,
19903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                               jstring content_type) {
20003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  URLRequestAdapter* request =
20103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
20203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SetPostContentType(env, request, content_type);
20303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
20403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request->EnableChunkedUpload();
20503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
20603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
20703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)static void AppendChunk(JNIEnv* env,
20803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                        jobject object,
20903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                        jlong urlRequestAdapter,
21003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                        jobject chunk_byte_buffer,
21103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                        jint chunk_size,
21203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                        jboolean is_last_chunk) {
21303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  URLRequestAdapter* request =
21403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
21503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK(chunk_byte_buffer != NULL);
21603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
21703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void* chunk = env->GetDirectBufferAddress(chunk_byte_buffer);
21803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request->AppendChunk(
21903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      reinterpret_cast<const char*>(chunk), chunk_size, is_last_chunk);
22003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
22103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch/* synchronized */
2236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static void Start(JNIEnv* env, jobject object, jlong urlRequestAdapter) {
2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* request =
2256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (request != NULL) {
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    request->Start();
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch/* synchronized */
2326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static void DestroyRequestAdapter(JNIEnv* env,
2336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                  jobject object,
2346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                  jlong urlRequestAdapter) {
2356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* request =
2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (request != NULL) {
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    request->Destroy();
239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch/* synchronized */
2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static void Cancel(JNIEnv* env, jobject object, jlong urlRequestAdapter) {
2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* request =
2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
246c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (request != NULL) {
247c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    request->Cancel();
248c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static jint GetErrorCode(JNIEnv* env, jobject object, jlong urlRequestAdapter) {
2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* request =
2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
254c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int error_code = request->error_code();
255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  switch (error_code) {
256c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // TODO(mef): Investigate returning success on positive values, too, as
257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // they technically indicate success.
258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case net::OK:
259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return REQUEST_ERROR_SUCCESS;
260c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // TODO(mef): Investigate this. The fact is that Chrome does not do this,
262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // and this library is not just being used for downloads.
263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Comment from src/content/browser/download/download_resource_handler.cc:
265c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // ERR_CONTENT_LENGTH_MISMATCH and ERR_INCOMPLETE_CHUNKED_ENCODING are
266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // allowed since a number of servers in the wild close the connection too
267c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // early by mistake. Other browsers - IE9, Firefox 11.0, and Safari 5.1.4 -
268c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // treat downloads as complete in both cases, so we follow their lead.
269c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case net::ERR_CONTENT_LENGTH_MISMATCH:
270c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case net::ERR_INCOMPLETE_CHUNKED_ENCODING:
271c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return REQUEST_ERROR_SUCCESS;
272c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
273c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case net::ERR_INVALID_URL:
274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case net::ERR_DISALLOWED_URL_SCHEME:
275c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case net::ERR_UNKNOWN_URL_SCHEME:
276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return REQUEST_ERROR_MALFORMED_URL;
277c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
278c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case net::ERR_CONNECTION_TIMED_OUT:
279c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return REQUEST_ERROR_CONNECTION_TIMED_OUT;
280c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
281c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case net::ERR_NAME_NOT_RESOLVED:
282c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return REQUEST_ERROR_UNKNOWN_HOST;
283c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
284c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return REQUEST_ERROR_UNKNOWN;
285c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
286c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
287c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic jstring GetErrorString(JNIEnv* env,
288c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                              jobject object,
2896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                              jlong urlRequestAdapter) {
2906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* request =
2916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
292c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int error_code = request->error_code();
293c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  char buffer[200];
2946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string error_string = net::ErrorToString(error_code);
295c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  snprintf(buffer,
296c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch           sizeof(buffer),
297c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch           "System error: %s(%d)",
2986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)           error_string.c_str(),
299c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch           error_code);
300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return ConvertUTF8ToJavaString(env, buffer).Release();
301c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
302c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
303c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic jint GetHttpStatusCode(JNIEnv* env,
304c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                              jobject object,
3056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                              jlong urlRequestAdapter) {
3066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* request =
3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
308c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return request->http_status_code();
309c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
310c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
311c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic jstring GetContentType(JNIEnv* env,
312c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                              jobject object,
3136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                              jlong urlRequestAdapter) {
3146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* request =
3156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
316c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (request == NULL) {
317c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return NULL;
318c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
319c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::string type = request->content_type();
320c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!type.empty()) {
321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return ConvertUTF8ToJavaString(env, type.c_str()).Release();
322c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  } else {
323c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return NULL;
324c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
325c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
326c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
327c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic jlong GetContentLength(JNIEnv* env,
328c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                              jobject object,
3296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                              jlong urlRequestAdapter) {
3306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* request =
3316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
332c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (request == NULL) {
333c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return 0;
334c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
335c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return request->content_length();
336c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
337c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
3386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static jstring GetHeader(JNIEnv* env,
3396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                         jobject object,
3406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                         jlong urlRequestAdapter,
3416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                         jstring name) {
3426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* request =
3436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (request == NULL) {
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return NULL;
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string name_string = base::android::ConvertJavaStringToUTF8(env, name);
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string value = request->GetHeader(name_string);
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!value.empty()) {
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ConvertUTF8ToJavaString(env, value.c_str()).Release();
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return NULL;
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void GetAllHeaders(JNIEnv* env,
3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          jobject object,
3596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                          jlong urlRequestAdapter,
3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          jobject headersMap) {
3616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  URLRequestAdapter* request =
3626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (request == NULL)
3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  net::HttpResponseHeaders* headers = request->GetResponseHeaders();
3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (headers == NULL)
3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void* iter = NULL;
3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::string header_name;
3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::string header_value;
3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  while (headers->EnumerateHeaderLines(&iter, &header_name, &header_value)) {
3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ScopedJavaLocalRef<jstring> name =
3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ConvertUTF8ToJavaString(env, header_name);
3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ScopedJavaLocalRef<jstring> value =
3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ConvertUTF8ToJavaString(env, header_value);
3786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    Java_ChromiumUrlRequest_onAppendResponseHeader(
3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        env, object, headersMap, name.Release(), value.Release());
3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Some implementations (notably HttpURLConnection) include a mapping for the
3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // null key; in HTTP's case, this maps to the HTTP status line.
3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ScopedJavaLocalRef<jstring> status_line =
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ConvertUTF8ToJavaString(env, headers->GetStatusLine());
3866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  Java_ChromiumUrlRequest_onAppendResponseHeader(
3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      env, object, headersMap, NULL, status_line.Release());
3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic jstring GetNegotiatedProtocol(JNIEnv* env,
3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                     jobject object,
3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                     jlong urlRequestAdapter) {
3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  URLRequestAdapter* request =
3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      reinterpret_cast<URLRequestAdapter*>(urlRequestAdapter);
3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (request == NULL)
3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return ConvertUTF8ToJavaString(env, "").Release();
3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string negotiated_protocol = request->GetNegotiatedProtocol();
3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return ConvertUTF8ToJavaString(env, negotiated_protocol.c_str()).Release();
4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}  // namespace cronet
403