OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/base/ime/remote_input_method_win.h" | 5 #include "ui/base/ime/remote_input_method_win.h" |
6 | 6 |
7 #include <InputScope.h> | 7 #include <InputScope.h> |
8 | 8 |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/scoped_observer.h" |
12 #include "base/strings/string16.h" | 13 #include "base/strings/string16.h" |
13 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
14 #include "ui/base/ime/dummy_text_input_client.h" | 15 #include "ui/base/ime/dummy_text_input_client.h" |
15 #include "ui/base/ime/input_method.h" | 16 #include "ui/base/ime/input_method.h" |
16 #include "ui/base/ime/input_method_delegate.h" | 17 #include "ui/base/ime/input_method_delegate.h" |
| 18 #include "ui/base/ime/input_method_observer.h" |
17 #include "ui/base/ime/remote_input_method_delegate_win.h" | 19 #include "ui/base/ime/remote_input_method_delegate_win.h" |
18 #include "ui/events/event.h" | 20 #include "ui/events/event.h" |
19 | 21 |
20 namespace ui { | 22 namespace ui { |
21 namespace { | 23 namespace { |
22 | 24 |
23 class MockTextInputClient : public DummyTextInputClient { | 25 class MockTextInputClient : public DummyTextInputClient { |
24 public: | 26 public: |
25 MockTextInputClient() | 27 MockTextInputClient() |
26 : text_input_type_(TEXT_INPUT_TYPE_NONE), | 28 : text_input_type_(TEXT_INPUT_TYPE_NONE), |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 composition_character_bounds_ = composition_character_bounds; | 156 composition_character_bounds_ = composition_character_bounds; |
155 } | 157 } |
156 | 158 |
157 bool cancel_composition_called_; | 159 bool cancel_composition_called_; |
158 bool text_input_client_updated_called_; | 160 bool text_input_client_updated_called_; |
159 std::vector<int32> input_scopes_; | 161 std::vector<int32> input_scopes_; |
160 std::vector<gfx::Rect> composition_character_bounds_; | 162 std::vector<gfx::Rect> composition_character_bounds_; |
161 DISALLOW_COPY_AND_ASSIGN(MockRemoteInputMethodDelegateWin); | 163 DISALLOW_COPY_AND_ASSIGN(MockRemoteInputMethodDelegateWin); |
162 }; | 164 }; |
163 | 165 |
| 166 class MockInputMethodObserver : public InputMethodObserver { |
| 167 public: |
| 168 MockInputMethodObserver() |
| 169 : on_text_input_type_changed_(0), |
| 170 on_caret_bounds_changed_(0), |
| 171 on_input_locale_changed_(0), |
| 172 on_text_input_state_changed_(0), |
| 173 on_input_method_destroyed_changed_(0) { |
| 174 } |
| 175 virtual ~MockInputMethodObserver() { |
| 176 } |
| 177 void Reset() { |
| 178 on_text_input_type_changed_ = 0; |
| 179 on_caret_bounds_changed_ = 0; |
| 180 on_input_locale_changed_ = 0; |
| 181 on_text_input_state_changed_ = 0; |
| 182 on_input_method_destroyed_changed_ = 0; |
| 183 } |
| 184 size_t on_text_input_type_changed() const { |
| 185 return on_text_input_type_changed_; |
| 186 } |
| 187 size_t on_caret_bounds_changed() const { |
| 188 return on_caret_bounds_changed_; |
| 189 } |
| 190 size_t on_input_locale_changed() const { |
| 191 return on_input_locale_changed_; |
| 192 } |
| 193 size_t on_text_input_state_changed() const { |
| 194 return on_text_input_state_changed_; |
| 195 } |
| 196 size_t on_input_method_destroyed_changed() const { |
| 197 return on_input_method_destroyed_changed_; |
| 198 } |
| 199 |
| 200 private: |
| 201 // Overriden from InputMethodObserver. |
| 202 virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE { |
| 203 ++on_text_input_type_changed_; |
| 204 } |
| 205 virtual void OnFocus() OVERRIDE { |
| 206 } |
| 207 virtual void OnBlur() OVERRIDE { |
| 208 } |
| 209 virtual void OnUntranslatedIMEMessage( |
| 210 const base::NativeEvent& event) OVERRIDE { |
| 211 } |
| 212 virtual void OnCaretBoundsChanged(const TextInputClient* client) OVERRIDE { |
| 213 ++on_caret_bounds_changed_; |
| 214 } |
| 215 virtual void OnInputLocaleChanged() OVERRIDE { |
| 216 ++on_input_locale_changed_; |
| 217 } |
| 218 virtual void OnTextInputStateChanged(const TextInputClient* client) OVERRIDE { |
| 219 ++on_text_input_state_changed_; |
| 220 } |
| 221 virtual void OnInputMethodDestroyed(const InputMethod* client) OVERRIDE { |
| 222 ++on_input_method_destroyed_changed_; |
| 223 } |
| 224 |
| 225 size_t on_text_input_type_changed_; |
| 226 size_t on_caret_bounds_changed_; |
| 227 size_t on_input_locale_changed_; |
| 228 size_t on_text_input_state_changed_; |
| 229 size_t on_input_method_destroyed_changed_; |
| 230 DISALLOW_COPY_AND_ASSIGN(MockInputMethodObserver); |
| 231 }; |
| 232 |
| 233 typedef ScopedObserver<InputMethod, InputMethodObserver> |
| 234 InputMethodScopedObserver; |
| 235 |
164 TEST(RemoteInputMethodWinTest, RemoteInputMethodPrivateWin) { | 236 TEST(RemoteInputMethodWinTest, RemoteInputMethodPrivateWin) { |
165 InputMethod* other_ptr = static_cast<InputMethod*>(NULL) + 1; | 237 InputMethod* other_ptr = static_cast<InputMethod*>(NULL) + 1; |
166 | 238 |
167 // Use typed NULL to make EXPECT_NE happy until nullptr becomes available. | 239 // Use typed NULL to make EXPECT_NE happy until nullptr becomes available. |
168 RemoteInputMethodPrivateWin* kNull = | 240 RemoteInputMethodPrivateWin* kNull = |
169 static_cast<RemoteInputMethodPrivateWin*>(NULL); | 241 static_cast<RemoteInputMethodPrivateWin*>(NULL); |
170 EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(other_ptr)); | 242 EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(other_ptr)); |
171 | 243 |
172 MockInputMethodDelegate delegate_; | 244 MockInputMethodDelegate delegate_; |
173 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_)); | 245 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_)); |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size()); | 363 ASSERT_EQ(1, mock_remote_delegate.input_scopes().size()); |
292 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]); | 364 EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]); |
293 | 365 |
294 // State must be cleared by DetachTextInputClient | 366 // State must be cleared by DetachTextInputClient |
295 mock_remote_delegate.Reset(); | 367 mock_remote_delegate.Reset(); |
296 input_method->DetachTextInputClient(&mock_text_input_client); | 368 input_method->DetachTextInputClient(&mock_text_input_client); |
297 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called()); | 369 EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called()); |
298 EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty()); | 370 EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty()); |
299 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty()); | 371 EXPECT_TRUE(mock_remote_delegate.input_scopes().empty()); |
300 } | 372 } |
| 373 |
301 TEST(RemoteInputMethodWinTest, OnCaretBoundsChanged) { | 374 TEST(RemoteInputMethodWinTest, OnCaretBoundsChanged) { |
302 MockInputMethodDelegate delegate_; | 375 MockInputMethodDelegate delegate_; |
303 MockTextInputClient mock_text_input_client; | 376 MockTextInputClient mock_text_input_client; |
304 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_)); | 377 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_)); |
305 | 378 |
306 // This must not cause a crash. | 379 // This must not cause a crash. |
307 input_method->OnCaretBoundsChanged(&mock_text_input_client); | 380 input_method->OnCaretBoundsChanged(&mock_text_input_client); |
308 | 381 |
309 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20)); | 382 mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20)); |
310 input_method->SetFocusedTextInputClient(&mock_text_input_client); | 383 input_method->SetFocusedTextInputClient(&mock_text_input_client); |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 | 638 |
566 // TextInputClient is now focused here. | 639 // TextInputClient is now focused here. |
567 | 640 |
568 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char)); | 641 EXPECT_TRUE(input_method->DispatchKeyEvent(fabricated_char)); |
569 EXPECT_EQ(L"A", mock_text_input_client.inserted_text()); | 642 EXPECT_EQ(L"A", mock_text_input_client.inserted_text()); |
570 EXPECT_TRUE(delegate_.fabricated_key_events().empty()); | 643 EXPECT_TRUE(delegate_.fabricated_key_events().empty()); |
571 delegate_.Reset(); | 644 delegate_.Reset(); |
572 mock_text_input_client.Reset(); | 645 mock_text_input_client.Reset(); |
573 } | 646 } |
574 | 647 |
| 648 TEST(RemoteInputMethodWinTest, OnTextInputStateChanged_Observer) { |
| 649 DummyTextInputClient text_input_client; |
| 650 DummyTextInputClient text_input_client_the_other; |
| 651 |
| 652 MockInputMethodObserver input_method_observer; |
| 653 MockInputMethodDelegate delegate_; |
| 654 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_)); |
| 655 InputMethodScopedObserver scoped_observer(&input_method_observer); |
| 656 scoped_observer.Add(input_method.get()); |
| 657 |
| 658 input_method->SetFocusedTextInputClient(&text_input_client); |
| 659 ASSERT_EQ(&text_input_client, input_method->GetTextInputClient()); |
| 660 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed()); |
| 661 input_method_observer.Reset(); |
| 662 |
| 663 input_method->SetFocusedTextInputClient(&text_input_client); |
| 664 ASSERT_EQ(&text_input_client, input_method->GetTextInputClient()); |
| 665 EXPECT_EQ(0u, input_method_observer.on_text_input_state_changed()); |
| 666 input_method_observer.Reset(); |
| 667 |
| 668 input_method->SetFocusedTextInputClient(&text_input_client_the_other); |
| 669 ASSERT_EQ(&text_input_client_the_other, input_method->GetTextInputClient()); |
| 670 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed()); |
| 671 input_method_observer.Reset(); |
| 672 |
| 673 input_method->DetachTextInputClient(&text_input_client_the_other); |
| 674 ASSERT_TRUE(input_method->GetTextInputClient() == NULL); |
| 675 EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed()); |
| 676 input_method_observer.Reset(); |
| 677 } |
| 678 |
| 679 TEST(RemoteInputMethodWinTest, OnCaretBoundsChanged_Observer) { |
| 680 DummyTextInputClient text_input_client; |
| 681 DummyTextInputClient text_input_client_the_other; |
| 682 |
| 683 MockInputMethodObserver input_method_observer; |
| 684 MockInputMethodDelegate delegate_; |
| 685 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_)); |
| 686 InputMethodScopedObserver scoped_observer(&input_method_observer); |
| 687 scoped_observer.Add(input_method.get()); |
| 688 |
| 689 { |
| 690 SCOPED_TRACE("OnCaretBoundsChanged callback must not be fired when no text " |
| 691 "input client is focused"); |
| 692 ASSERT_EQ(NULL, input_method->GetTextInputClient()); |
| 693 |
| 694 input_method_observer.Reset(); |
| 695 input_method->OnCaretBoundsChanged(&text_input_client); |
| 696 EXPECT_EQ(0u, input_method_observer.on_caret_bounds_changed()); |
| 697 input_method->OnCaretBoundsChanged(NULL); |
| 698 EXPECT_EQ(0u, input_method_observer.on_caret_bounds_changed()); |
| 699 } |
| 700 |
| 701 { |
| 702 SCOPED_TRACE("OnCaretBoundsChanged callback must be fired when and only " |
| 703 "the event is notified from the focused text input client"); |
| 704 |
| 705 input_method->SetFocusedTextInputClient(&text_input_client); |
| 706 ASSERT_EQ(&text_input_client, input_method->GetTextInputClient()); |
| 707 |
| 708 // Must fire the event |
| 709 input_method_observer.Reset(); |
| 710 input_method->OnCaretBoundsChanged(&text_input_client); |
| 711 EXPECT_EQ(1u, input_method_observer.on_caret_bounds_changed()); |
| 712 |
| 713 // Must not fire the event |
| 714 input_method_observer.Reset(); |
| 715 input_method->OnCaretBoundsChanged(NULL); |
| 716 EXPECT_EQ(0u, input_method_observer.on_caret_bounds_changed()); |
| 717 |
| 718 // Must not fire the event |
| 719 input_method_observer.Reset(); |
| 720 input_method->OnCaretBoundsChanged(&text_input_client_the_other); |
| 721 EXPECT_EQ(0u, input_method_observer.on_caret_bounds_changed()); |
| 722 } |
| 723 } |
| 724 |
| 725 TEST(RemoteInputMethodWinTest, OnInputLocaleChanged_Observer) { |
| 726 DummyTextInputClient text_input_client; |
| 727 |
| 728 MockInputMethodObserver input_method_observer; |
| 729 |
| 730 MockInputMethodDelegate delegate_; |
| 731 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_)); |
| 732 InputMethodScopedObserver scoped_observer(&input_method_observer); |
| 733 scoped_observer.Add(input_method.get()); |
| 734 |
| 735 { |
| 736 SCOPED_TRACE("OnInputLocaleChanged callback can be fired even when no text " |
| 737 "input client is focused"); |
| 738 ASSERT_EQ(NULL, input_method->GetTextInputClient()); |
| 739 |
| 740 input_method_observer.Reset(); |
| 741 input_method->OnInputLocaleChanged(); |
| 742 EXPECT_EQ(1u, input_method_observer.on_input_locale_changed()); |
| 743 |
| 744 input_method->SetFocusedTextInputClient(&text_input_client); |
| 745 input_method_observer.Reset(); |
| 746 input_method->OnInputLocaleChanged(); |
| 747 EXPECT_EQ(1u, input_method_observer.on_input_locale_changed()); |
| 748 } |
| 749 } |
| 750 |
| 751 TEST(RemoteInputMethodWinTest, OnInputMethodDestroyed_Observer) { |
| 752 DummyTextInputClient text_input_client; |
| 753 DummyTextInputClient text_input_client_the_other; |
| 754 |
| 755 MockInputMethodObserver input_method_observer; |
| 756 InputMethodScopedObserver scoped_observer(&input_method_observer); |
| 757 |
| 758 MockInputMethodDelegate delegate_; |
| 759 scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_)); |
| 760 input_method->AddObserver(&input_method_observer); |
| 761 |
| 762 EXPECT_EQ(0u, input_method_observer.on_input_method_destroyed_changed()); |
| 763 input_method.reset(); |
| 764 EXPECT_EQ(1u, input_method_observer.on_input_method_destroyed_changed()); |
| 765 } |
| 766 |
575 } // namespace | 767 } // namespace |
576 } // namespace ui | 768 } // namespace ui |
OLD | NEW |