summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-03 05:23:19 +0000
committerhbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-03 05:23:19 +0000
commit14fa2eb42feec5805b6df55d4eb2c1c5897649c5 (patch)
tree872aceaab9599ade9522882200ef345e05e298bd
parent7a5f33d653f43e6effd8247b2a3a623ec80c95b0 (diff)
downloadchromium_src-14fa2eb42feec5805b6df55d4eb2c1c5897649c5.zip
chromium_src-14fa2eb42feec5805b6df55d4eb2c1c5897649c5.tar.gz
chromium_src-14fa2eb42feec5805b6df55d4eb2c1c5897649c5.tar.bz2
Make our IME backend platform-independent.
This change makes our IME backend run not only on Windows but also on Linux and Mac. This change also adds another unit-test which verifies the backend runs on Linux and Mac without problems. Review URL: http://codereview.chromium.org/27124 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10783 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.cc6
-rw-r--r--chrome/common/render_messages_internal.h8
-rw-r--r--chrome/renderer/render_view.h1
-rw-r--r--chrome/renderer/render_view_unittest.cc128
-rw-r--r--webkit/glue/webview_impl.cc6
5 files changed, 138 insertions, 11 deletions
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc
index e0ed23e..1139000 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc
@@ -699,7 +699,7 @@ LRESULT RenderWidgetHostViewWin::OnImeComposition(
ImeComposition composition;
if (ime_input_.GetResult(m_hWnd, lparam, &composition)) {
Send(new ViewMsg_ImeSetComposition(render_widget_host_->routing_id(),
- composition.string_type,
+ 1,
composition.cursor_position,
composition.target_start,
composition.target_end,
@@ -714,7 +714,7 @@ LRESULT RenderWidgetHostViewWin::OnImeComposition(
// composition and send it to a renderer process.
if (ime_input_.GetComposition(m_hWnd, lparam, &composition)) {
Send(new ViewMsg_ImeSetComposition(render_widget_host_->routing_id(),
- composition.string_type,
+ 0,
composition.cursor_position,
composition.target_start,
composition.target_end,
@@ -735,7 +735,7 @@ LRESULT RenderWidgetHostViewWin::OnImeEndComposition(
// of the renderer process.
std::wstring empty_string;
Send(new ViewMsg_ImeSetComposition(render_widget_host_->routing_id(),
- 0, -1, -1, -1, empty_string));
+ -1, -1, -1, -1, empty_string));
ime_input_.ResetComposition(m_hWnd);
}
ime_input_.DestroyImeWindow(m_hWnd);
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 902ac0b..41b18a6 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -331,12 +331,12 @@ IPC_BEGIN_MESSAGES(View)
// This message sends a string being composed with IME.
// Parameters
// * string_type (int)
- // Represents the type of the string in the 'ime_string' parameter.
+ // Represents the type of the 'ime_string' parameter.
// Its possible values and description are listed below:
// Value Description
- // 0 The parameter is not used.
- // GCS_RESULTSTR The parameter represents a result string.
- // GCS_COMPSTR The parameter represents a composition string.
+ // -1 The parameter is not used.
+ // 1 The parameter represents a result string.
+ // 0 The parameter represents a composition string.
// * cursor_position (int)
// Represents the position of the cursor
// * target_start (int)
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index bbccfec..3ce6c3c 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -371,6 +371,7 @@ class RenderView : public RenderWidget,
FRIEND_TEST(RenderViewTest, OnLoadAlternateHTMLText);
FRIEND_TEST(RenderViewTest, OnNavStateChanged);
FRIEND_TEST(RenderViewTest, OnImeStateChanged);
+ FRIEND_TEST(RenderViewTest, ImeComposition);
explicit RenderView(RenderThreadBase* render_thread);
diff --git a/chrome/renderer/render_view_unittest.cc b/chrome/renderer/render_view_unittest.cc
index 31a5348..283bd2d 100644
--- a/chrome/renderer/render_view_unittest.cc
+++ b/chrome/renderer/render_view_unittest.cc
@@ -191,3 +191,131 @@ TEST_F(RenderViewTest, OnImeStateChanged) {
}
}
+// Test that our IME backend can compose CJK words.
+// Our IME front-end sends many platform-independent messages to the IME backend
+// while it composes CJK words. This test sends the minimal messages captured
+// on my local environment directly to the IME backend to verify if the backend
+// can compose CJK words without any problems.
+// This test uses an array of command sets because an IME composotion does not
+// only depends on IME events, but also depends on window events, e.g. moving
+// the window focus while composing a CJK text. To handle such complicated
+// cases, this test should not only call IME-related functions in the
+// RenderWidget class, but also call some RenderWidget members, e.g.
+// ExecuteJavaScript(), RenderWidget::OnSetFocus(), etc.
+TEST_F(RenderViewTest, ImeComposition) {
+ enum ImeCommand {
+ IME_INITIALIZE,
+ IME_SETINPUTMODE,
+ IME_SETFOCUS,
+ IME_SETCOMPOSITION,
+ };
+ struct ImeMessage {
+ ImeCommand command;
+ bool enable;
+ int string_type;
+ int cursor_position;
+ int target_start;
+ int target_end;
+ const wchar_t* ime_string;
+ const wchar_t* result;
+ };
+ static const ImeMessage kImeMessages[] = {
+ // Scenario 1: input a Chinese word with Microsoft IME (on Vista).
+ {IME_INITIALIZE, true, 0, 0, 0, 0, NULL, NULL},
+ {IME_SETINPUTMODE, true, 0, 0, 0, 0, NULL, NULL},
+ {IME_SETFOCUS, true, 0, 0, 0, 0, NULL, NULL},
+ {IME_SETCOMPOSITION, false, 0, 1, -1, -1, L"n", L"n"},
+ {IME_SETCOMPOSITION, false, 0, 2, -1, -1, L"ni", L"ni"},
+ {IME_SETCOMPOSITION, false, 0, 3, -1, -1, L"nih", L"nih"},
+ {IME_SETCOMPOSITION, false, 0, 4, -1, -1, L"niha", L"niha"},
+ {IME_SETCOMPOSITION, false, 0, 5, -1, -1, L"nihao", L"nihao"},
+ {IME_SETCOMPOSITION, false, 0, 2, -1, -1, L"\x4F60\x597D", L"\x4F60\x597D"},
+ {IME_SETCOMPOSITION, false, 1, -1, -1, -1, L"\x4F60\x597D",
+ L"\x4F60\x597D"},
+ {IME_SETCOMPOSITION, false, -1, -1, -1, -1, L"", L"\x4F60\x597D"},
+ // Scenario 2: input a Japanese word with Microsoft IME (on Vista).
+ {IME_INITIALIZE, true, 0, 0, 0, 0, NULL, NULL},
+ {IME_SETINPUTMODE, true, 0, 0, 0, 0, NULL, NULL},
+ {IME_SETFOCUS, true, 0, 0, 0, 0, NULL, NULL},
+ {IME_SETCOMPOSITION, false, 0, 1, 0, 1, L"\xFF4B", L"\xFF4B"},
+ {IME_SETCOMPOSITION, false, 0, 1, 0, 1, L"\x304B", L"\x304B"},
+ {IME_SETCOMPOSITION, false, 0, 2, 0, 2, L"\x304B\xFF4E", L"\x304B\xFF4E"},
+ {IME_SETCOMPOSITION, false, 0, 3, 0, 3, L"\x304B\x3093\xFF4A",
+ L"\x304B\x3093\xFF4A"},
+ {IME_SETCOMPOSITION, false, 0, 3, 0, 3, L"\x304B\x3093\x3058",
+ L"\x304B\x3093\x3058"},
+ {IME_SETCOMPOSITION, false, 0, 0, 0, 2, L"\x611F\x3058", L"\x611F\x3058"},
+ {IME_SETCOMPOSITION, false, 0, 0, 0, 2, L"\x6F22\x5B57", L"\x6F22\x5B57"},
+ {IME_SETCOMPOSITION, false, 1, -1, -1, -1, L"\x6F22\x5B57",
+ L"\x6F22\x5B57"},
+ {IME_SETCOMPOSITION, false, -1, -1, -1, -1, L"", L"\x6F22\x5B57"},
+ // Scenario 3: input a Korean word with Microsot IME (on Vista).
+ {IME_INITIALIZE, true, 0, 0, 0, 0, NULL, NULL},
+ {IME_SETINPUTMODE, true, 0, 0, 0, 0, NULL, NULL},
+ {IME_SETFOCUS, true, 0, 0, 0, 0, NULL, NULL},
+ {IME_SETCOMPOSITION, false, 0, 0, 0, 1, L"\x3147", L"\x3147"},
+ {IME_SETCOMPOSITION, false, 0, 0, 0, 1, L"\xC544", L"\xC544"},
+ {IME_SETCOMPOSITION, false, 0, 0, 0, 1, L"\xC548", L"\xC548"},
+ {IME_SETCOMPOSITION, false, 1, -1, -1, -1, L"\xC548", L"\xC548"},
+ {IME_SETCOMPOSITION, false, 0, 0, 0, 1, L"\x3134", L"\xC548\x3134"},
+ {IME_SETCOMPOSITION, false, 0, 0, 0, 1, L"\xB140", L"\xC548\xB140"},
+ {IME_SETCOMPOSITION, false, 0, 0, 0, 1, L"\xB155", L"\xC548\xB155"},
+ {IME_SETCOMPOSITION, false, -1, -1, -1, -1, L"", L"\xC548"},
+ {IME_SETCOMPOSITION, false, 1, -1, -1, -1, L"\xB155", L"\xC548\xB155"},
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kImeMessages); i++) {
+ const ImeMessage* ime_message = &kImeMessages[i];
+ switch (ime_message->command) {
+ case IME_INITIALIZE:
+ // Load an HTML page consisting of a content-editable <div> element,
+ // and move the input focus to the <div> element, where we can use
+ // IMEs.
+ view_->OnImeSetInputMode(ime_message->enable);
+ view_->set_delay_seconds_for_form_state_sync(0);
+ LoadHTML("<html>"
+ "<head>"
+ "</head>"
+ "<body>"
+ "<div id=\"test1\" contenteditable=\"true\"></div>"
+ "</body>"
+ "</html>");
+ ExecuteJavaScript("document.getElementById('test1').focus();");
+ break;
+
+ case IME_SETINPUTMODE:
+ // Activate (or deactivate) our IME back-end.
+ view_->OnImeSetInputMode(ime_message->enable);
+ break;
+
+ case IME_SETFOCUS:
+ // Update the window focus.
+ view_->OnSetFocus(ime_message->enable);
+ break;
+
+ case IME_SETCOMPOSITION:
+ view_->OnImeSetComposition(ime_message->string_type,
+ ime_message->cursor_position,
+ ime_message->target_start,
+ ime_message->target_end,
+ ime_message->ime_string);
+ break;
+ }
+
+ // Update the status of our IME back-end.
+ // TODO(hbono): we should verify messages to be sent from the back-end.
+ view_->UpdateIME();
+ ProcessPendingMessages();
+ render_thread_.sink().ClearMessages();
+
+ if (ime_message->result) {
+ // Retrieve the content of this page and compare it with the expected
+ // result.
+ const int kMaxOutputCharacters = 128;
+ std::wstring output;
+ GetMainFrame()->GetContentAsPlainText(kMaxOutputCharacters, &output);
+ EXPECT_EQ(output, ime_message->result);
+ }
+ }
+}
+
diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc
index dca001d..2fac917 100644
--- a/webkit/glue/webview_impl.cc
+++ b/webkit/glue/webview_impl.cc
@@ -1125,7 +1125,7 @@ bool WebViewImpl::ImeSetComposition(int string_type,
return false;
}
- if (string_type == 0) {
+ if (string_type == -1) {
// A browser process sent an IPC message which does not contain a valid
// string, which means an ongoing composition has been canceled.
// If the ongoing composition has been canceled, replace the ongoing
@@ -1165,14 +1165,12 @@ bool WebViewImpl::ImeSetComposition(int string_type,
// there are not any characters in the above region.
editor->setComposition(composition_string, underlines,
cursor_position, cursor_position);
-#if defined(OS_WIN)
// The given string is a result string, which means the ongoing
// composition has been completed. I have to call the
// Editor::confirmCompletion() and complete this composition.
- if (string_type == GCS_RESULTSTR) {
+ if (string_type == 1) {
editor->confirmComposition();
}
-#endif
}
return editor->hasComposition();