diff options
Diffstat (limited to 'ppapi')
-rw-r--r-- | ppapi/ppapi_shared_proxy.gypi | 3 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 14 | ||||
-rw-r--r-- | ppapi/proxy/ppb_char_set_proxy.cc | 112 | ||||
-rw-r--r-- | ppapi/proxy/ppb_char_set_proxy.h | 20 | ||||
-rw-r--r-- | ppapi/shared_impl/char_set_impl.cc | 153 | ||||
-rw-r--r-- | ppapi/shared_impl/char_set_impl.h | 38 |
6 files changed, 210 insertions, 130 deletions
diff --git a/ppapi/ppapi_shared_proxy.gypi b/ppapi/ppapi_shared_proxy.gypi index 73212e9..0d2168c 100644 --- a/ppapi/ppapi_shared_proxy.gypi +++ b/ppapi/ppapi_shared_proxy.gypi @@ -10,6 +10,7 @@ 'dependencies': [ 'ppapi_c', '../base/base.gyp:base', + '../third_party/icu/icu.gyp:icuuc', ], 'include_dirs': [ '..', @@ -17,6 +18,8 @@ 'sources': [ 'shared_impl/audio_impl.cc', 'shared_impl/audio_impl.h', + 'shared_impl/char_set_impl.cc', + 'shared_impl/char_set_impl.h', 'shared_impl/image_data_impl.cc', 'shared_impl/image_data_impl.h', ], diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index 01cd6f1..c7f59f3 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -300,20 +300,6 @@ IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBCore_ReleaseResource, pp::proxy::HostResource) // PPB_CharSet. -IPC_SYNC_MESSAGE_ROUTED4_2(PpapiHostMsg_PPBCharSet_UTF16ToCharSet, - PP_Instance /* instance */, - string16 /* utf16 */, - std::string /* char_set */, - int32_t /* on_error */, - std::string /* output */, - bool /* output_is_success */) -IPC_SYNC_MESSAGE_ROUTED4_2(PpapiHostMsg_PPBCharSet_CharSetToUTF16, - PP_Instance /* instance */, - std::string /* input */, - std::string /* char_set */, - int32_t /* on_error */, - string16 /* output */, - bool /* output_is_success */) IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBCharSet_GetDefaultCharSet, PP_Instance /* instance */, pp::proxy::SerializedVar /* result */) diff --git a/ppapi/proxy/ppb_char_set_proxy.cc b/ppapi/proxy/ppb_char_set_proxy.cc index 35b6473..5c9c7d0 100644 --- a/ppapi/proxy/ppb_char_set_proxy.cc +++ b/ppapi/proxy/ppb_char_set_proxy.cc @@ -4,68 +4,42 @@ #include "ppapi/proxy/ppb_char_set_proxy.h" +#include "base/basictypes.h" #include "ppapi/c/dev/ppb_char_set_dev.h" #include "ppapi/c/ppb_core.h" #include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/serialized_var.h" +#include "ppapi/shared_impl/char_set_impl.h" namespace pp { namespace proxy { namespace { -char* UTF16ToCharSet(PP_Instance instance, +const PPB_Core* GetCoreInterface() { + return static_cast<const PPB_Core*>( + PluginDispatcher::GetInterfaceFromDispatcher(PPB_CORE_INTERFACE)); +} + +char* UTF16ToCharSet(PP_Instance /* instance */, const uint16_t* utf16, uint32_t utf16_len, const char* output_char_set, PP_CharSet_ConversionError on_error, uint32_t* output_length) { - *output_length = 0; - PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); - if (!dispatcher) - return NULL; - - bool output_is_success = false; - std::string result; - dispatcher->Send(new PpapiHostMsg_PPBCharSet_UTF16ToCharSet( - INTERFACE_ID_PPB_CHAR_SET, instance, - string16(reinterpret_cast<const char16*>(utf16), utf16_len), - std::string(output_char_set), static_cast<int32_t>(on_error), - &result, &output_is_success)); - if (!output_is_success) - return NULL; - - *output_length = static_cast<uint32_t>(result.size()); - char* ret_val = static_cast<char*>(malloc(result.size() + 1)); - memcpy(ret_val, result.c_str(), result.size() + 1); - return ret_val; + return pp::shared_impl::CharSetImpl::UTF16ToCharSet( + GetCoreInterface(), utf16, utf16_len, output_char_set, on_error, + output_length); } -uint16_t* CharSetToUTF16(PP_Instance instance, +uint16_t* CharSetToUTF16(PP_Instance /* instance */, const char* input, uint32_t input_len, const char* input_char_set, PP_CharSet_ConversionError on_error, uint32_t* output_length) { - *output_length = 0; - PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); - if (!dispatcher) - return NULL; - - bool output_is_success = false; - string16 result; - dispatcher->Send(new PpapiHostMsg_PPBCharSet_CharSetToUTF16( - INTERFACE_ID_PPB_CHAR_SET, instance, - std::string(input, input_len), - std::string(input_char_set), static_cast<int32_t>(on_error), - &result, &output_is_success)); - if (!output_is_success) - return NULL; - - *output_length = static_cast<uint32_t>(result.size()); - uint16_t* ret_val = static_cast<uint16_t*>( - malloc((result.size() + 1) * sizeof(uint16_t))); - memcpy(ret_val, result.c_str(), (result.size() + 1) * sizeof(uint16_t)); - return ret_val; + return pp::shared_impl::CharSetImpl::CharSetToUTF16( + GetCoreInterface(), input, input_len, input_char_set, on_error, + output_length); } PP_Var GetDefaultCharSet(PP_Instance instance) { @@ -94,8 +68,7 @@ InterfaceProxy* CreateCharSetProxy(Dispatcher* dispatcher, PPB_CharSet_Proxy::PPB_CharSet_Proxy(Dispatcher* dispatcher, const void* target_interface) - : InterfaceProxy(dispatcher, target_interface), - core_interface_(NULL) { + : InterfaceProxy(dispatcher, target_interface) { } PPB_CharSet_Proxy::~PPB_CharSet_Proxy() { @@ -116,10 +89,6 @@ const InterfaceProxy::Info* PPB_CharSet_Proxy::GetInfo() { bool PPB_CharSet_Proxy::OnMessageReceived(const IPC::Message& msg) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(PPB_CharSet_Proxy, msg) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCharSet_UTF16ToCharSet, - OnMsgUTF16ToCharSet) - IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCharSet_CharSetToUTF16, - OnMsgCharSetToUTF16) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBCharSet_GetDefaultCharSet, OnMsgGetDefaultCharSet) IPC_MESSAGE_UNHANDLED(handled = false) @@ -127,47 +96,6 @@ bool PPB_CharSet_Proxy::OnMessageReceived(const IPC::Message& msg) { return handled; } -void PPB_CharSet_Proxy::OnMsgUTF16ToCharSet(PP_Instance instance, - const string16& utf16, - const std::string& char_set, - int32_t on_error, - std::string* output, - bool* output_is_success) { - uint32_t output_len = 0; - char* result = ppb_char_set_target()->UTF16ToCharSet( - instance, reinterpret_cast<const uint16_t*>(utf16.c_str()), - static_cast<uint32_t>(utf16.size()), - char_set.c_str(), static_cast<PP_CharSet_ConversionError>(on_error), - &output_len); - if (result) { - output->assign(result, output_len); - GetCoreInterface()->MemFree(result); - *output_is_success = true; - } else { - *output_is_success = false; - } -} - -void PPB_CharSet_Proxy::OnMsgCharSetToUTF16(PP_Instance instance, - const std::string& input, - const std::string& char_set, - int32_t on_error, - string16* output, - bool* output_is_success) { - uint32_t output_len = 0; - uint16_t* result = ppb_char_set_target()->CharSetToUTF16( - instance, input.c_str(), static_cast<uint32_t>(input.size()), - char_set.c_str(), static_cast<PP_CharSet_ConversionError>(on_error), - &output_len); - if (result) { - output->assign(reinterpret_cast<const char16*>(result), output_len); - GetCoreInterface()->MemFree(result); - *output_is_success = true; - } else { - *output_is_success = false; - } -} - void PPB_CharSet_Proxy::OnMsgGetDefaultCharSet( PP_Instance instance, SerializedVarReturnValue result) { @@ -175,13 +103,5 @@ void PPB_CharSet_Proxy::OnMsgGetDefaultCharSet( ppb_char_set_target()->GetDefaultCharSet(instance)); } -const PPB_Core* PPB_CharSet_Proxy::GetCoreInterface() { - if (!core_interface_) { - core_interface_ = static_cast<const PPB_Core*>( - dispatcher()->GetLocalInterface(PPB_CORE_INTERFACE)); - } - return core_interface_; -} - } // namespace proxy } // namespace pp diff --git a/ppapi/proxy/ppb_char_set_proxy.h b/ppapi/proxy/ppb_char_set_proxy.h index 91360b1..f6af048 100644 --- a/ppapi/proxy/ppb_char_set_proxy.h +++ b/ppapi/proxy/ppb_char_set_proxy.h @@ -5,7 +5,6 @@ #ifndef PPAPI_PROXY_PPB_CHAR_SET_PROXY_H_ #define PPAPI_PROXY_PPB_CHAR_SET_PROXY_H_ -#include "base/basictypes.h" #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_resource.h" #include "ppapi/proxy/interface_proxy.h" @@ -33,28 +32,9 @@ class PPB_CharSet_Proxy : public InterfaceProxy { virtual bool OnMessageReceived(const IPC::Message& msg); private: - // Message handlers. - void OnMsgUTF16ToCharSet(PP_Instance instance, - const string16& utf16, - const std::string& char_set, - int32_t on_error, - std::string* output, - bool* output_is_success); - void OnMsgCharSetToUTF16(PP_Instance instance, - const std::string& input, - const std::string& char_set, - int32_t on_error, - string16* output, - bool* output_is_success); void OnMsgGetDefaultCharSet(PP_Instance instance, SerializedVarReturnValue result); - // Returns the local PPB_Core interface for freeing strings. - const PPB_Core* GetCoreInterface(); - - // Possibly NULL, lazily initialized by GetCoreInterface. - const PPB_Core* core_interface_; - DISALLOW_COPY_AND_ASSIGN(PPB_CharSet_Proxy); }; diff --git a/ppapi/shared_impl/char_set_impl.cc b/ppapi/shared_impl/char_set_impl.cc new file mode 100644 index 0000000..012f9d6 --- /dev/null +++ b/ppapi/shared_impl/char_set_impl.cc @@ -0,0 +1,153 @@ +// Copyright (c) 2011 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 "ppapi/shared_impl/char_set_impl.h" + +#include "base/i18n/icu_string_conversions.h" +#include "ppapi/c/ppb_core.h" +#include "unicode/ucnv.h" +#include "unicode/ucnv_cb.h" +#include "unicode/ucnv_err.h" +#include "unicode/ustring.h" + +namespace pp { +namespace shared_impl { + +namespace { + +// Converts the given PP error handling behavior to the version in base, +// placing the result in |*result| and returning true on success. Returns false +// if the enum is invalid. +bool PPToBaseConversionError(PP_CharSet_ConversionError on_error, + base::OnStringConversionError::Type* result) { + switch (on_error) { + case PP_CHARSET_CONVERSIONERROR_FAIL: + *result = base::OnStringConversionError::FAIL; + return true; + case PP_CHARSET_CONVERSIONERROR_SKIP: + *result = base::OnStringConversionError::SKIP; + return true; + case PP_CHARSET_CONVERSIONERROR_SUBSTITUTE: + *result = base::OnStringConversionError::SUBSTITUTE; + return true; + default: + return false; + } +} + +} // namespace + +// static +// The "substitution" behavior of this function does not match the +// implementation in base, so we partially duplicate the code from +// icu_string_conversions.cc with the correct error handling setup required +// by the PPAPI interface. +char* CharSetImpl::UTF16ToCharSet(const PPB_Core* core, + const uint16_t* utf16, + uint32_t utf16_len, + const char* output_char_set, + PP_CharSet_ConversionError on_error, + uint32_t* output_length) { + if (!core || !utf16 || !output_char_set || !output_length) + return NULL; + + *output_length = 0; + + UErrorCode status = U_ZERO_ERROR; + UConverter* converter = ucnv_open(output_char_set, &status); + if (!U_SUCCESS(status)) + return NULL; + + int encoded_max_length = UCNV_GET_MAX_BYTES_FOR_STRING(utf16_len, + ucnv_getMaxCharSize(converter)); + + // Setup our error handler. + switch (on_error) { + case PP_CHARSET_CONVERSIONERROR_FAIL: + ucnv_setFromUCallBack(converter, UCNV_FROM_U_CALLBACK_STOP, 0, + NULL, NULL, &status); + break; + case PP_CHARSET_CONVERSIONERROR_SKIP: + ucnv_setFromUCallBack(converter, UCNV_FROM_U_CALLBACK_SKIP, 0, + NULL, NULL, &status); + break; + case PP_CHARSET_CONVERSIONERROR_SUBSTITUTE: { + // ICU sets the substitution char for some character sets (like latin1) + // to be the ASCII "substitution character" (26). We want to use '?' + // instead for backwards-compat with Windows behavior. + char subst_chars[32]; + int8_t subst_chars_len = 32; + ucnv_getSubstChars(converter, subst_chars, &subst_chars_len, &status); + if (subst_chars_len == 1 && subst_chars[0] == 26) { + // Override to the question mark character if possible. When using + // setSubstString, the input is a Unicode character. The function will + // try to convert it to the destination character set and fail if that + // can not be converted to the destination character set. + // + // We just ignore any failure. If the dest char set has no + // representation for '?', then we'll just stick to the ICU default + // substitution character. + UErrorCode subst_status = U_ZERO_ERROR; + UChar question_mark = '?'; + ucnv_setSubstString(converter, &question_mark, 1, &subst_status); + } + + ucnv_setFromUCallBack(converter, UCNV_FROM_U_CALLBACK_SUBSTITUTE, 0, + NULL, NULL, &status); + break; + } + default: + return NULL; + } + + // ucnv_fromUChars returns size not including terminating null. + char* encoded = static_cast<char*>(core->MemAlloc(encoded_max_length + 1)); + int actual_size = ucnv_fromUChars(converter, encoded, + encoded_max_length, reinterpret_cast<const UChar*>(utf16), utf16_len, + &status); + ucnv_close(converter); + if (!U_SUCCESS(status)) { + core->MemFree(encoded); + return NULL; + } + encoded[actual_size] = 0; + *output_length = actual_size; + return encoded; +} + +// static +uint16_t* CharSetImpl::CharSetToUTF16(const PPB_Core* core, + const char* input, + uint32_t input_len, + const char* input_char_set, + PP_CharSet_ConversionError on_error, + uint32_t* output_length) { + if (!core || !input || !input_char_set || !output_length) + return NULL; + + *output_length = 0; + + base::OnStringConversionError::Type base_on_error; + if (!PPToBaseConversionError(on_error, &base_on_error)) + return NULL; // Invalid enum value. + + // We can convert this call to the implementation in base to avoid code + // duplication, although this does introduce an extra copy of the data. + string16 output; + if (!base::CodepageToUTF16(std::string(input, input_len), input_char_set, + base_on_error, &output)) + return NULL; + + uint16_t* ret_buf = static_cast<uint16_t*>( + core->MemAlloc((output.size() + 1) * sizeof(uint16_t))); + if (!ret_buf) + return NULL; + + *output_length = static_cast<uint32_t>(output.size()); + memcpy(ret_buf, output.c_str(), (output.size() + 1) * sizeof(uint16_t)); + return ret_buf; +} + +} // namespace shared_impl +} // namespace pp diff --git a/ppapi/shared_impl/char_set_impl.h b/ppapi/shared_impl/char_set_impl.h new file mode 100644 index 0000000..985a5d6 --- /dev/null +++ b/ppapi/shared_impl/char_set_impl.h @@ -0,0 +1,38 @@ +// Copyright (c) 2011 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 PPAPI_SHARED_IMPL_CHAR_SET_IMPL_H_ +#define PPAPI_SHARED_IMPL_CHAR_SET_IMPL_H_ + +#include "base/basictypes.h" +#include "ppapi/c/dev/ppb_char_set_dev.h" + +struct PPB_Core; + +namespace pp { +namespace shared_impl { + +// Contains the implementation of character set conversion that is shared +// between the proxy and the renderer. +class CharSetImpl { + public: + static char* UTF16ToCharSet(const PPB_Core* core, + const uint16_t* utf16, + uint32_t utf16_len, + const char* output_char_set, + PP_CharSet_ConversionError on_error, + uint32_t* output_length); + + static uint16_t* CharSetToUTF16(const PPB_Core* core, + const char* input, + uint32_t input_len, + const char* input_char_set, + PP_CharSet_ConversionError on_error, + uint32_t* output_length); +}; + +} // namespace shared_impl +} // namespace pp + +#endif // PPAPI_SHARED_IMPL_CHAR_SET_IMPL_H_ |