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