1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be 3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file. 4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/android/jni_string.h" 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/android/jni_android.h" 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/logging.h" 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/strings/utf_string_conversions.h" 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace { 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Internal version that does not use a scoped local pointer. 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezjstring ConvertUTF16ToJavaStringImpl(JNIEnv* env, 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const base::StringPiece16& str) { 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez jstring result = env->NewString(str.data(), str.length()); 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::android::CheckException(env); 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return result; 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace base { 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace android { 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid ConvertJavaStringToUTF8(JNIEnv* env, jstring str, std::string* result) { 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(str); 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!str) { 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG(WARNING) << "ConvertJavaStringToUTF8 called with null string."; 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez result->clear(); 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const jsize length = env->GetStringLength(str); 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!length) { 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez result->clear(); 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CheckException(env); 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // JNI's GetStringUTFChars() returns strings in Java "modified" UTF8, so 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // instead get the String in UTF16 and convert using chromium's conversion 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // function that yields plain (non Java-modified) UTF8. 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const jchar* chars = env->GetStringChars(str, NULL); 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(chars); 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UTF16ToUTF8(chars, length, result); 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez env->ReleaseStringChars(str, chars); 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CheckException(env); 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstd::string ConvertJavaStringToUTF8(JNIEnv* env, jstring str) { 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::string result; 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ConvertJavaStringToUTF8(env, str, &result); 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return result; 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstd::string ConvertJavaStringToUTF8(const JavaRef<jstring>& str) { 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return ConvertJavaStringToUTF8(AttachCurrentThread(), str.obj()); 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstd::string ConvertJavaStringToUTF8(JNIEnv* env, const JavaRef<jstring>& str) { 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return ConvertJavaStringToUTF8(env, str.obj()); 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezScopedJavaLocalRef<jstring> ConvertUTF8ToJavaString( 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez JNIEnv* env, 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const base::StringPiece& str) { 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // JNI's NewStringUTF expects "modified" UTF8 so instead create the string 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // via our own UTF16 conversion utility. 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Further, Dalvik requires the string passed into NewStringUTF() to come from 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // a trusted source. We can't guarantee that all UTF8 will be sanitized before 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // it gets here, so constructing via UTF16 side-steps this issue. 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // (Dalvik stores strings internally as UTF16 anyway, so there shouldn't be 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // a significant performance hit by doing it this way). 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return ScopedJavaLocalRef<jstring>(env, ConvertUTF16ToJavaStringImpl( 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez env, UTF8ToUTF16(str))); 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid ConvertJavaStringToUTF16(JNIEnv* env, jstring str, string16* result) { 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(str); 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!str) { 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG(WARNING) << "ConvertJavaStringToUTF16 called with null string."; 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez result->clear(); 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const jsize length = env->GetStringLength(str); 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!length) { 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez result->clear(); 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CheckException(env); 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const jchar* chars = env->GetStringChars(str, NULL); 91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(chars); 92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // GetStringChars isn't required to NULL-terminate the strings 93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // it returns, so the length must be explicitly checked. 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez result->assign(chars, length); 95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez env->ReleaseStringChars(str, chars); 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CheckException(env); 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstring16 ConvertJavaStringToUTF16(JNIEnv* env, jstring str) { 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez string16 result; 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ConvertJavaStringToUTF16(env, str, &result); 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return result; 103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstring16 ConvertJavaStringToUTF16(const JavaRef<jstring>& str) { 106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return ConvertJavaStringToUTF16(AttachCurrentThread(), str.obj()); 107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstring16 ConvertJavaStringToUTF16(JNIEnv* env, const JavaRef<jstring>& str) { 110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return ConvertJavaStringToUTF16(env, str.obj()); 111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezScopedJavaLocalRef<jstring> ConvertUTF16ToJavaString( 114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez JNIEnv* env, 115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const base::StringPiece16& str) { 116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return ScopedJavaLocalRef<jstring>(env, 117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ConvertUTF16ToJavaStringImpl(env, str)); 118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace android 121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace base 122