1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/base/net_string_util_icu_alternatives_android.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/android/jni_android.h"
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/android/jni_string.h"
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/strings/string16.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/strings/string_piece.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "jni/NetStringUtil_jni.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/base/net_string_util.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace net {
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Attempts to convert |text| encoded in |charset| to a jstring (Java unicode
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// string).  Returns the result jstring, or NULL on failure.
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ScopedJavaLocalRef<jstring> ConvertToJstring(const std::string& text,
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                             const char* charset) {
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  JNIEnv* env = base::android::AttachCurrentThread();
236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ScopedJavaLocalRef<jobject> java_byte_buffer(
246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      env,
256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length()));
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::android::ScopedJavaLocalRef<jstring> java_charset =
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset));
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedJavaLocalRef<jstring> java_result =
296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      android::Java_NetStringUtil_convertToUnicode(env, java_byte_buffer.obj(),
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                   java_charset.obj());
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return java_result;
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Attempts to convert |text| encoded in |charset| to a jstring (Java unicode
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// string) and then normalizes the string.  Returns the result jstring, or NULL
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// on failure.
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ScopedJavaLocalRef<jstring> ConvertToNormalizedJstring(
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& text, const char* charset) {
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  JNIEnv* env = base::android::AttachCurrentThread();
406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ScopedJavaLocalRef<jobject> java_byte_buffer(
416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      env,
426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length()));
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::android::ScopedJavaLocalRef<jstring> java_charset =
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset));
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedJavaLocalRef<jstring> java_result =
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      android::Java_NetStringUtil_convertToUnicodeAndNormalize(
476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          env, java_byte_buffer.obj(), java_charset.obj());
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return java_result;
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Converts |text| encoded in |charset| to a jstring (Java unicode string).
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Any characters that can not be converted are replaced with U+FFFD.
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ScopedJavaLocalRef<jstring> ConvertToJstringWithSubstitutions(
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& text, const char* charset) {
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  JNIEnv* env = base::android::AttachCurrentThread();
566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ScopedJavaLocalRef<jobject> java_byte_buffer(
576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      env,
586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length()));
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::android::ScopedJavaLocalRef<jstring> java_charset =
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset));
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedJavaLocalRef<jstring> java_result =
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      android::Java_NetStringUtil_convertToUnicodeWithSubstitutions(
636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          env, java_byte_buffer.obj(), java_charset.obj());
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return java_result;
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char* const kCharsetLatin1 = "ISO-8859-1";
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ConvertToUtf8(const std::string& text, const char* charset,
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   std::string* output) {
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  output->clear();
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedJavaLocalRef<jstring> java_result = ConvertToJstring(text, charset);
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (java_result.is_null())
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *output = base::android::ConvertJavaStringToUTF8(java_result);
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ConvertToUtf8AndNormalize(const std::string& text, const char* charset,
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               std::string* output) {
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  output->clear();
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedJavaLocalRef<jstring> java_result = ConvertToNormalizedJstring(
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      text, charset);
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (java_result.is_null())
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *output = base::android::ConvertJavaStringToUTF8(java_result);
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ConvertToUTF16(const std::string& text, const char* charset,
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    base::string16* output) {
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  output->clear();
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedJavaLocalRef<jstring> java_result = ConvertToJstring(text, charset);
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (java_result.is_null())
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *output = base::android::ConvertJavaStringToUTF16(java_result);
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool ConvertToUTF16WithSubstitutions(const std::string& text,
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                     const char* charset,
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                     base::string16* output) {
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  output->clear();
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedJavaLocalRef<jstring> java_result =
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)     ConvertToJstringWithSubstitutions(text, charset);
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (java_result.is_null())
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *output = base::android::ConvertJavaStringToUTF16(java_result);
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool RegisterNetStringUtils(JNIEnv* env) {
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return android::RegisterNativesImpl(env);
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace net
119