summaryrefslogtreecommitdiffstats
path: root/ppapi
diff options
context:
space:
mode:
authoryzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-15 17:57:00 +0000
committeryzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-15 17:57:00 +0000
commit26f9e71c23a1ef0b4716ef3e4e0747992dd7911f (patch)
tree55ef36bdc69a08c11eae979c37f56c9dcf468753 /ppapi
parentc394e045bfe187e5c88f47b238b9259ffea88ae4 (diff)
downloadchromium_src-26f9e71c23a1ef0b4716ef3e4e0747992dd7911f.zip
chromium_src-26f9e71c23a1ef0b4716ef3e4e0747992dd7911f.tar.gz
chromium_src-26f9e71c23a1ef0b4716ef3e4e0747992dd7911f.tar.bz2
Run PPB_CharSet_Dev logic directly in the plugin process.
- Move part of the character set conversion logic into ppapi/shared_impl/char_set_impl.{h,cc}. - Change ppb_char_set_proxy to use it directly in the plugin process. - Another minor change is to avoid using malloc/free during character set conversion, and use PPB_Core.MemAlloc/MemFree instead. BUG=none TEST=Pass test_char_set.{h,cc} Review URL: http://codereview.chromium.org/6694011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@78232 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
-rw-r--r--ppapi/ppapi_shared_proxy.gypi3
-rw-r--r--ppapi/proxy/ppapi_messages.h14
-rw-r--r--ppapi/proxy/ppb_char_set_proxy.cc112
-rw-r--r--ppapi/proxy/ppb_char_set_proxy.h20
-rw-r--r--ppapi/shared_impl/char_set_impl.cc153
-rw-r--r--ppapi/shared_impl/char_set_impl.h38
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_