jni_string.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/android/jni_string.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/android/jni_android.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Internal version that does not use a scoped local pointer. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)jstring ConvertUTF16ToJavaStringImpl(JNIEnv* env, 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::StringPiece16& str) { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jstring result = env->NewString(str.data(), str.length()); 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::android::CheckException(env); 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace android { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ConvertJavaStringToUTF8(JNIEnv* env, jstring str, std::string* result) { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!str) { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "ConvertJavaStringToUTF8 called with null string."; 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result->clear(); 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // JNI's GetStringUTFChars() returns strings in Java "modified" UTF8, so 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // instead get the String in UTF16 and convert using chromium's conversion 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // function that yields plain (non Java-modified) UTF8. 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const jchar* chars = env->GetStringChars(str, NULL); 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(chars); 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UTF16ToUTF8(chars, env->GetStringLength(str), result); 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) env->ReleaseStringChars(str, chars); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CheckException(env); 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ConvertJavaStringToUTF8(JNIEnv* env, jstring str) { 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string result; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ConvertJavaStringToUTF8(env, str, &result); 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return result; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ConvertJavaStringToUTF8(const JavaRef<jstring>& str) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ConvertJavaStringToUTF8(AttachCurrentThread(), str.obj()); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedJavaLocalRef<jstring> ConvertUTF8ToJavaString( 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JNIEnv* env, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::StringPiece& str) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // JNI's NewStringUTF expects "modified" UTF8 so instead create the string 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // via our own UTF16 conversion utility. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Further, Dalvik requires the string passed into NewStringUTF() to come from 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a trusted source. We can't guarantee that all UTF8 will be sanitized before 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it gets here, so constructing via UTF16 side-steps this issue. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (Dalvik stores strings internally as UTF16 anyway, so there shouldn't be 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a significant performance hit by doing it this way). 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ScopedJavaLocalRef<jstring>(env, ConvertUTF16ToJavaStringImpl( 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env, UTF8ToUTF16(str))); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ConvertJavaStringToUTF16(JNIEnv* env, jstring str, string16* result) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!str) { 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "ConvertJavaStringToUTF16 called with null string."; 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result->clear(); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const jchar* chars = env->GetStringChars(str, NULL); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(chars); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GetStringChars isn't required to NULL-terminate the strings 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it returns, so the length must be explicitly checked. 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result->assign(chars, env->GetStringLength(str)); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env->ReleaseStringChars(str, chars); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckException(env); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)string16 ConvertJavaStringToUTF16(JNIEnv* env, jstring str) { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string16 result; 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ConvertJavaStringToUTF16(env, str, &result); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 ConvertJavaStringToUTF16(const JavaRef<jstring>& str) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ConvertJavaStringToUTF16(AttachCurrentThread(), str.obj()); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedJavaLocalRef<jstring> ConvertUTF16ToJavaString( 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JNIEnv* env, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::StringPiece16& str) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ScopedJavaLocalRef<jstring>(env, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConvertUTF16ToJavaStringImpl(env, str)); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace android 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 100