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