diff options
author | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-10 18:32:47 +0000 |
---|---|---|
committer | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-10 18:32:47 +0000 |
commit | de36240ae4c0ccec2d96b17e2390fd89b936e94d (patch) | |
tree | 10d06c71f7b38d6ed439ad7a67af604c1263a0e0 /net | |
parent | cbdf6d505803f1467d90f5cfa2624a0d51386422 (diff) | |
download | chromium_src-de36240ae4c0ccec2d96b17e2390fd89b936e94d.zip chromium_src-de36240ae4c0ccec2d96b17e2390fd89b936e94d.tar.gz chromium_src-de36240ae4c0ccec2d96b17e2390fd89b936e94d.tar.bz2 |
Implement alternative string conversion functions in net/ on Android,
using Java conversion functions. This is part of making it possible
to build net/ without ICU, to get binary size down when building net/
as a library
BUG=362608
Review URL: https://codereview.chromium.org/266053002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269595 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/DEPS | 4 | ||||
-rw-r--r-- | net/android/java/src/org/chromium/net/NetStringUtil.java | 89 | ||||
-rw-r--r-- | net/android/net_jni_registrar.cc | 7 | ||||
-rw-r--r-- | net/base/net_string_util.h | 15 | ||||
-rw-r--r-- | net/base/net_string_util_icu.cc | 16 | ||||
-rw-r--r-- | net/base/net_string_util_icu_alternatives_android.cc | 115 | ||||
-rw-r--r-- | net/base/net_string_util_icu_alternatives_android.h | 18 | ||||
-rw-r--r-- | net/cert/x509_cert_types_mac.cc | 2 | ||||
-rw-r--r-- | net/http/http_auth_handler_basic.cc | 4 | ||||
-rw-r--r-- | net/http/http_auth_handler_digest.cc | 2 | ||||
-rw-r--r-- | net/net.gyp | 18 | ||||
-rw-r--r-- | net/proxy/proxy_script_fetcher_impl.cc | 13 |
12 files changed, 272 insertions, 31 deletions
@@ -44,10 +44,6 @@ specific_include_rules = { "+third_party/icu/source/common/unicode/ucnv.h" ], - # Only use icu for string conversions. - "proxy_script_fetcher_impl\.cc": [ - "+base/i18n/icu_string_conversions.h", - ], "websocket_channel\.h": [ "+base/i18n", ], diff --git a/net/android/java/src/org/chromium/net/NetStringUtil.java b/net/android/java/src/org/chromium/net/NetStringUtil.java new file mode 100644 index 0000000..4ab1bd9 --- /dev/null +++ b/net/android/java/src/org/chromium/net/NetStringUtil.java @@ -0,0 +1,89 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.net; + +import org.chromium.base.CalledByNative; +import org.chromium.base.JNINamespace; + +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CodingErrorAction; +import java.text.Normalizer; + +/** + * Utility functions for converting strings between formats when not built with + * icu. + */ +@JNINamespace("net::android") +public class NetStringUtil { + /** + * Attempts to convert text in a given character set to a Unicode string. + * Returns null on failure. + * @param text ByteBuffer containing the character array to convert. + * @param charset Character set it's in encoded in. + * @return: Unicode string on success, null on failure. + */ + @CalledByNative + private static String convertToUnicode( + ByteBuffer text, + String charset_name) { + try { + Charset charset = Charset.forName(charset_name); + CharsetDecoder decoder = charset.newDecoder(); + // On invalid characters, this will throw an exception. + return decoder.decode(text).toString(); + } catch (Exception e) { + return null; + } + } + + /** + * Attempts to convert text in a given character set to a Unicode string, + * and normalize it. Returns null on failure. + * @param text ByteBuffer containing the character array to convert. + * @param charset Character set it's in encoded in. + * @return: Unicode string on success, null on failure. + */ + @CalledByNative + private static String convertToUnicodeAndNormalize( + ByteBuffer text, + String charset_name) { + String unicodeString = convertToUnicode(text, charset_name); + if (unicodeString == null) + return unicodeString; + return Normalizer.normalize(unicodeString, Normalizer.Form.NFC); + } + + /** + * Convert text in a given character set to a Unicode string. Any invalid + * characters are replaced with U+FFFD. Returns null if the character set + * is not recognized. + * @param text ByteBuffer containing the character array to convert. + * @param charset Character set it's in encoded in. + * @return: Unicode string on success, null on failure. + */ + @CalledByNative + private static String convertToUnicodeWithSubstitutions( + ByteBuffer text, + String charset_name) { + try { + Charset charset = Charset.forName(charset_name); + + // TODO(mmenke): Investigate if Charset.decode() can be used + // instead. The question is whether it uses the proper replace + // character. JDK CharsetDecoder docs say U+FFFD is the default, + // but Charset.decode() docs say it uses the "charset's default + // replacement byte array". + CharsetDecoder decoder = charset.newDecoder(); + decoder.onMalformedInput(CodingErrorAction.REPLACE); + decoder.onUnmappableCharacter(CodingErrorAction.REPLACE); + decoder.replaceWith("\uFFFD"); + return decoder.decode(text).toString(); + } catch (Exception e) { + return null; + } + } +} diff --git a/net/android/net_jni_registrar.cc b/net/android/net_jni_registrar.cc index b3e9437..ebc7276 100644 --- a/net/android/net_jni_registrar.cc +++ b/net/android/net_jni_registrar.cc @@ -15,6 +15,10 @@ #include "net/cert/x509_util_android.h" #include "net/proxy/proxy_config_service_android.h" +#if defined(USE_ICU_ALTERNATIVES) +#include "net/base/net_string_util_icu_alternatives_android.h" +#endif + namespace net { namespace android { @@ -28,6 +32,9 @@ static base::android::RegistrationMethod kNetRegisteredMethods[] = { net::NetworkChangeNotifierAndroid::Register }, { "ProxyConfigService", net::ProxyConfigServiceAndroid::Register }, { "X509Util", net::RegisterX509Util }, +#if defined(USE_ICU_ALTERNATIVES) + { "NetStringUtils", net::RegisterNetStringUtils } +#endif }; bool RegisterJni(JNIEnv* env) { diff --git a/net/base/net_string_util.h b/net/base/net_string_util.h index ce5fdf5..8e959a0 100644 --- a/net/base/net_string_util.h +++ b/net/base/net_string_util.h @@ -14,6 +14,8 @@ namespace net { +extern const char* const kCharsetLatin1; + // Converts |text| using |charset| to UTF-8, and writes it to |output|. // On failure, returns false and |output| is cleared. bool ConvertToUtf8(const std::string& text, const char* charset, @@ -24,19 +26,16 @@ bool ConvertToUtf8(const std::string& text, const char* charset, bool ConvertToUtf8AndNormalize(const std::string& text, const char* charset, std::string* output); -// Converts |text| encoded in Latin-1 to UTF-8, normalizes the result, and -// writes it to |output|. On failure, returns false and |output| is cleared. -bool ConvertLatin1ToUtf8AndNormalize(const std::string& text, - std::string* output); - // Converts |text| using |charset| to UTF-16, and writes it to |output|. // On failure, returns false and |output| is cleared. bool ConvertToUTF16(const std::string& text, const char* charset, base::string16* output); -// Converts |text| encoded in Latin-1 to UTF-16, and writes it to |output|. -// On failure, returns false and |output| is cleared. -bool ConvertLatin1ToUTF16(const std::string& text, base::string16* output); +// Converts |text| using |charset| to UTF-16, and writes it to |output|. +// Any characters that can not be converted are replaced with U+FFFD. +bool ConvertToUTF16WithSubstitutions(const std::string& text, + const char* charset, + base::string16* output); } // namespace net diff --git a/net/base/net_string_util_icu.cc b/net/base/net_string_util_icu.cc index f8a1ce7..435f9de 100644 --- a/net/base/net_string_util_icu.cc +++ b/net/base/net_string_util_icu.cc @@ -11,6 +11,8 @@ namespace net { +const char* const kCharsetLatin1 = base::kCodepageLatin1; + bool ConvertToUtf8(const std::string& text, const char* charset, std::string* output) { output->clear(); @@ -43,20 +45,18 @@ bool ConvertToUtf8AndNormalize(const std::string& text, const char* charset, return base::ConvertToUtf8AndNormalize(text, charset, output); } -bool ConvertLatin1ToUtf8AndNormalize(const std::string& text, - std::string* output) { - return net::ConvertToUtf8AndNormalize(text, base::kCodepageLatin1, output); -} - bool ConvertToUTF16(const std::string& text, const char* charset, base::string16* output) { return base::CodepageToUTF16(text, charset, base::OnStringConversionError::FAIL, output); } -bool ConvertLatin1ToUTF16(const std::string& text, base::string16* output) { - return base::CodepageToUTF16(text, base::kCodepageLatin1, - base::OnStringConversionError::FAIL, output); +bool ConvertToUTF16WithSubstitutions(const std::string& text, + const char* charset, + base::string16* output) { + return base::CodepageToUTF16(text, charset, + base::OnStringConversionError::SUBSTITUTE, + output); } } // namespace net diff --git a/net/base/net_string_util_icu_alternatives_android.cc b/net/base/net_string_util_icu_alternatives_android.cc new file mode 100644 index 0000000..ca06303 --- /dev/null +++ b/net/base/net_string_util_icu_alternatives_android.cc @@ -0,0 +1,115 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/net_string_util_icu_alternatives_android.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "base/strings/string16.h" +#include "base/strings/string_piece.h" +#include "jni/NetStringUtil_jni.h" +#include "net/base/net_string_util.h" + +namespace net { + +namespace { + +// Attempts to convert |text| encoded in |charset| to a jstring (Java unicode +// string). Returns the result jstring, or NULL on failure. +ScopedJavaLocalRef<jstring> ConvertToJstring(const std::string& text, + const char* charset) { + JNIEnv* env = base::android::AttachCurrentThread(); + jobject java_byte_buffer = + env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length()); + base::android::ScopedJavaLocalRef<jstring> java_charset = + base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset)); + ScopedJavaLocalRef<jstring> java_result = + android::Java_NetStringUtil_convertToUnicode(env, java_byte_buffer, + java_charset.obj()); + return java_result; +} + +// Attempts to convert |text| encoded in |charset| to a jstring (Java unicode +// string) and then normalizes the string. Returns the result jstring, or NULL +// on failure. +ScopedJavaLocalRef<jstring> ConvertToNormalizedJstring( + const std::string& text, const char* charset) { + JNIEnv* env = base::android::AttachCurrentThread(); + jobject java_byte_buffer = + env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length()); + base::android::ScopedJavaLocalRef<jstring> java_charset = + base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset)); + ScopedJavaLocalRef<jstring> java_result = + android::Java_NetStringUtil_convertToUnicodeAndNormalize( + env, java_byte_buffer, java_charset.obj()); + return java_result; +} + +// Converts |text| encoded in |charset| to a jstring (Java unicode string). +// Any characters that can not be converted are replaced with U+FFFD. +ScopedJavaLocalRef<jstring> ConvertToJstringWithSubstitutions( + const std::string& text, const char* charset) { + JNIEnv* env = base::android::AttachCurrentThread(); + jobject java_byte_buffer = + env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length()); + base::android::ScopedJavaLocalRef<jstring> java_charset = + base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset)); + ScopedJavaLocalRef<jstring> java_result = + android::Java_NetStringUtil_convertToUnicodeWithSubstitutions( + env, java_byte_buffer, java_charset.obj()); + return java_result; +} + +} // namespace + +const char* const kCharsetLatin1 = "ISO-8859-1"; + +bool ConvertToUtf8(const std::string& text, const char* charset, + std::string* output) { + output->clear(); + ScopedJavaLocalRef<jstring> java_result = ConvertToJstring(text, charset); + if (java_result.is_null()) + return false; + *output = base::android::ConvertJavaStringToUTF8(java_result); + return true; +} + +bool ConvertToUtf8AndNormalize(const std::string& text, const char* charset, + std::string* output) { + output->clear(); + ScopedJavaLocalRef<jstring> java_result = ConvertToNormalizedJstring( + text, charset); + if (java_result.is_null()) + return false; + *output = base::android::ConvertJavaStringToUTF8(java_result); + return true; +} + +bool ConvertToUTF16(const std::string& text, const char* charset, + base::string16* output) { + output->clear(); + ScopedJavaLocalRef<jstring> java_result = ConvertToJstring(text, charset); + if (java_result.is_null()) + return false; + *output = base::android::ConvertJavaStringToUTF16(java_result); + return true; +} + +bool ConvertToUTF16WithSubstitutions(const std::string& text, + const char* charset, + base::string16* output) { + output->clear(); + ScopedJavaLocalRef<jstring> java_result = + ConvertToJstringWithSubstitutions(text, charset); + if (java_result.is_null()) + return false; + *output = base::android::ConvertJavaStringToUTF16(java_result); + return true; +} + +bool RegisterNetStringUtils(JNIEnv* env) { + return android::RegisterNativesImpl(env); +} + +} // namespace net diff --git a/net/base/net_string_util_icu_alternatives_android.h b/net/base/net_string_util_icu_alternatives_android.h new file mode 100644 index 0000000..c3a6cf5 --- /dev/null +++ b/net/base/net_string_util_icu_alternatives_android.h @@ -0,0 +1,18 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_NET_STRING_UTIL_ICU_ALTERNATIVES_ANDROID_H_ +#define NET_BASE_NET_STRING_UTIL_ICU_ALTERNATIVES_ANDROID_H_ + +#include <jni.h> + +namespace net { + +// Explicitly register static JNI functions needed when not using ICU. +bool RegisterNetStringUtils(JNIEnv* env); + +} // namespace net + +#endif // NET_BASE_NET_STRING_UTIL_ICU_ALTERNATIVES_ANDROID_H_ + diff --git a/net/cert/x509_cert_types_mac.cc b/net/cert/x509_cert_types_mac.cc index 244fe99..d5b2ea3 100644 --- a/net/cert/x509_cert_types_mac.cc +++ b/net/cert/x509_cert_types_mac.cc @@ -115,7 +115,7 @@ std::string DataToString(CSSM_DATA data) { // Converts raw CSSM_DATA in ISO-8859-1 to a std::string in UTF-8. std::string Latin1DataToUTF8String(CSSM_DATA data) { base::string16 utf16; - if (!ConvertLatin1ToUTF16(DataToString(data), &utf16)) + if (!ConvertToUTF16(DataToString(data), kCharsetLatin1, &utf16)) return ""; return base::UTF16ToUTF8(utf16); } diff --git a/net/http/http_auth_handler_basic.cc b/net/http/http_auth_handler_basic.cc index eace1df..4837138 100644 --- a/net/http/http_auth_handler_basic.cc +++ b/net/http/http_auth_handler_basic.cc @@ -43,8 +43,10 @@ bool ParseRealm(const HttpAuthChallengeTokenizer& tokenizer, if (!LowerCaseEqualsASCII(parameters.name(), "realm")) continue; - if (!net::ConvertLatin1ToUtf8AndNormalize(parameters.value(), realm)) + if (!net::ConvertToUtf8AndNormalize(parameters.value(), kCharsetLatin1, + realm)) { return false; + } } return parameters.valid(); } diff --git a/net/http/http_auth_handler_digest.cc b/net/http/http_auth_handler_digest.cc index ce4b148..7dee081 100644 --- a/net/http/http_auth_handler_digest.cc +++ b/net/http/http_auth_handler_digest.cc @@ -227,7 +227,7 @@ bool HttpAuthHandlerDigest::ParseChallengeProperty(const std::string& name, const std::string& value) { if (LowerCaseEqualsASCII(name, "realm")) { std::string realm; - if (!net::ConvertLatin1ToUtf8AndNormalize(value, &realm)) + if (!net::ConvertToUtf8AndNormalize(value, kCharsetLatin1, &realm)) return false; realm_ = realm; original_realm_ = value; diff --git a/net/net.gyp b/net/net.gyp index 559a7dc..a454e7d 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -438,6 +438,16 @@ ], }, ], + [ 'use_icu_alternatives_on_android == 1', { + 'sources!': [ + 'base/net_string_util_icu.cc', + ], + 'sources': [ + 'base/net_string_util_icu_alternatives_android.cc', + 'base/net_string_util_icu_alternatives_android.h', + ], + }, + ], ], 'target_conditions': [ # These source files are excluded by default platform rules, but they @@ -1430,6 +1440,14 @@ 'jni_generator_ptr_type': 'long', }, 'includes': [ '../build/jni_generator.gypi' ], + + 'conditions': [ + ['use_icu_alternatives_on_android==1', { + 'sources': [ + 'android/java/src/org/chromium/net/NetStringUtil.java', + ], + }], + ], }, { 'target_name': 'net_test_jni_headers', diff --git a/net/proxy/proxy_script_fetcher_impl.cc b/net/proxy/proxy_script_fetcher_impl.cc index 0887d8c..737c6f8 100644 --- a/net/proxy/proxy_script_fetcher_impl.cc +++ b/net/proxy/proxy_script_fetcher_impl.cc @@ -5,7 +5,6 @@ #include "net/proxy/proxy_script_fetcher_impl.h" #include "base/compiler_specific.h" -#include "base/i18n/icu_string_conversions.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/strings/string_util.h" @@ -13,6 +12,7 @@ #include "net/base/io_buffer.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" +#include "net/base/net_string_util.h" #include "net/base/request_priority.h" #include "net/cert/cert_status_flags.h" #include "net/http/http_response_headers.h" @@ -56,18 +56,15 @@ void ConvertResponseToUTF16(const std::string& charset, if (charset.empty()) { // Assume ISO-8859-1 if no charset was specified. - codepage = base::kCodepageLatin1; + codepage = kCharsetLatin1; } else { // Otherwise trust the charset that was provided. codepage = charset.c_str(); } - // We will be generous in the conversion -- if any characters lie - // outside of |charset| (i.e. invalid), then substitute them with - // U+FFFD rather than failing. - base::CodepageToUTF16(bytes, codepage, - base::OnStringConversionError::SUBSTITUTE, - utf16); + // Be generous in the conversion -- if any characters lie outside of |charset| + // (i.e. invalid), then substitute them with U+FFFD rather than failing. + ConvertToUTF16WithSubstitutions(bytes, codepage, utf16); } } // namespace |