diff options
author | mohsen@chromium.org <mohsen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-20 06:28:57 +0000 |
---|---|---|
committer | mohsen@chromium.org <mohsen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-20 06:28:57 +0000 |
commit | a9d1cf623120165dfb55e8b6dc65d0e93e86a49d (patch) | |
tree | 2a7f74ad29242af93f9ea6ec467ec14b5dbf1282 | |
parent | 4ac74265832c7d7f74493eb3ff7d5136ebea7762 (diff) | |
download | chromium_src-a9d1cf623120165dfb55e8b6dc65d0e93e86a49d.zip chromium_src-a9d1cf623120165dfb55e8b6dc65d0e93e86a49d.tar.gz chromium_src-a9d1cf623120165dfb55e8b6dc65d0e93e86a49d.tar.bz2 |
Observe in views::InputMethodBridge if host IME is destroyed
Sometimes, before the widget and its corresponding input method bridge
is destroyed, the host input method used by the bridge is destroyed.
This can especially happen in unit tests. So, input method bridge should
observe the host input method to avoid calling methods on it if it is
destroyed.
The tests that were disabled because of this issue are re-enabled, too.
BUG=315883
Review URL: https://codereview.chromium.org/58903012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@236186 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | tools/heapcheck/ash_unittests.gtest-heapcheck.txt | 2 | ||||
-rw-r--r-- | tools/valgrind/gtest_exclude/ash_unittests.gtest-memcheck.txt | 5 | ||||
-rw-r--r-- | ui/views/ime/input_method_bridge.cc | 81 | ||||
-rw-r--r-- | ui/views/ime/input_method_bridge.h | 8 |
4 files changed, 86 insertions, 10 deletions
diff --git a/tools/heapcheck/ash_unittests.gtest-heapcheck.txt b/tools/heapcheck/ash_unittests.gtest-heapcheck.txt deleted file mode 100644 index c645144..0000000 --- a/tools/heapcheck/ash_unittests.gtest-heapcheck.txt +++ /dev/null @@ -1,2 +0,0 @@ -# Crashes - http://crbug.com/315883 -DragDropControllerTest.TouchDragDropInMultipleWindows diff --git a/tools/valgrind/gtest_exclude/ash_unittests.gtest-memcheck.txt b/tools/valgrind/gtest_exclude/ash_unittests.gtest-memcheck.txt deleted file mode 100644 index b7245e6..0000000 --- a/tools/valgrind/gtest_exclude/ash_unittests.gtest-memcheck.txt +++ /dev/null @@ -1,5 +0,0 @@ -# http://crbug.com/315883 -WindowManagerTest.ActivateOnTouch -DragDropControllerTest.TouchDragDropLongTapGestureIsForwarded -DragDropControllerTest.TouchDragDropCancelsOnLongTap -DragDropControllerTest.TouchDragDropInMultipleWindows diff --git a/ui/views/ime/input_method_bridge.cc b/ui/views/ime/input_method_bridge.cc index 5238313..ea13bd4 100644 --- a/ui/views/ime/input_method_bridge.cc +++ b/ui/views/ime/input_method_bridge.cc @@ -5,6 +5,7 @@ #include "ui/views/ime/input_method_bridge.h" #include "ui/base/ime/input_method.h" +#include "ui/base/ime/input_method_observer.h" #include "ui/events/event.h" #include "ui/gfx/rect.h" #include "ui/views/view.h" @@ -12,6 +13,55 @@ namespace views { +// InputMethodBridge::HostObserver class --------------------------------------- + +// An observer class for observing the host input method. When the host input +// method is destroyed, it will null out the |host_| field on the +// InputMethodBridge object. +class InputMethodBridge::HostObserver : public ui::InputMethodObserver { + public: + explicit HostObserver(InputMethodBridge* bridge); + virtual ~HostObserver(); + + virtual void OnTextInputTypeChanged( + const ui::TextInputClient* client) OVERRIDE {} + virtual void OnFocus() OVERRIDE {} + virtual void OnBlur() OVERRIDE {} + virtual void OnUntranslatedIMEMessage( + const base::NativeEvent& event) OVERRIDE {} + virtual void OnCaretBoundsChanged( + const ui::TextInputClient* client) OVERRIDE {} + virtual void OnInputLocaleChanged() OVERRIDE {} + virtual void OnTextInputStateChanged( + const ui::TextInputClient* client) OVERRIDE {} + virtual void OnInputMethodDestroyed( + const ui::InputMethod* input_method) OVERRIDE; + + private: + InputMethodBridge* bridge_; + + DISALLOW_COPY_AND_ASSIGN(HostObserver); +}; + +InputMethodBridge::HostObserver::HostObserver(InputMethodBridge* bridge) + : bridge_(bridge) { + bridge_->host_->AddObserver(this); +} + +InputMethodBridge::HostObserver::~HostObserver() { + if (bridge_->host_) + bridge_->host_->RemoveObserver(this); +} + +void InputMethodBridge::HostObserver::OnInputMethodDestroyed( + const ui::InputMethod* input_method) { + DCHECK_EQ(bridge_->host_, input_method); + bridge_->host_->RemoveObserver(this); + bridge_->host_ = NULL; +} + +// InputMethodBridge class ----------------------------------------------------- + InputMethodBridge::InputMethodBridge(internal::InputMethodDelegate* delegate, ui::InputMethod* host, bool shared_input_method) @@ -19,6 +69,8 @@ InputMethodBridge::InputMethodBridge(internal::InputMethodDelegate* delegate, shared_input_method_(shared_input_method) { DCHECK(host_); SetDelegate(delegate); + + host_observer_.reset(new HostObserver(this)); } InputMethodBridge::~InputMethodBridge() { @@ -28,10 +80,15 @@ InputMethodBridge::~InputMethodBridge() { // this and go into |widget_|. NULL out |widget_| so we don't attempt to use // it. DetachFromWidget(); - host_->DetachTextInputClient(this); + + // Host input method might have been destroyed at this point. + if (host_) + host_->DetachTextInputClient(this); } void InputMethodBridge::OnFocus() { + DCHECK(host_); + // Direct the shared IME to send TextInputClient messages to |this| object. if (shared_input_method_ || !host_->GetTextInputClient()) host_->SetFocusedTextInputClient(this); @@ -43,6 +100,8 @@ void InputMethodBridge::OnFocus() { } void InputMethodBridge::OnBlur() { + DCHECK(host_); + if (HasCompositionText()) { ConfirmCompositionText(); host_->CancelComposition(this); @@ -54,6 +113,8 @@ void InputMethodBridge::OnBlur() { bool InputMethodBridge::OnUntranslatedIMEMessage(const base::NativeEvent& event, NativeEventResult* result) { + DCHECK(host_); + return host_->OnUntranslatedIMEMessage(event, result); } @@ -66,38 +127,54 @@ void InputMethodBridge::DispatchKeyEvent(const ui::KeyEvent& key) { } void InputMethodBridge::OnTextInputTypeChanged(View* view) { + DCHECK(host_); + if (IsViewFocused(view)) host_->OnTextInputTypeChanged(this); InputMethodBase::OnTextInputTypeChanged(view); } void InputMethodBridge::OnCaretBoundsChanged(View* view) { + DCHECK(host_); + if (IsViewFocused(view) && !IsTextInputTypeNone()) host_->OnCaretBoundsChanged(this); } void InputMethodBridge::CancelComposition(View* view) { + DCHECK(host_); + if (IsViewFocused(view)) host_->CancelComposition(this); } void InputMethodBridge::OnInputLocaleChanged() { - return host_->OnInputLocaleChanged(); + DCHECK(host_); + + host_->OnInputLocaleChanged(); } std::string InputMethodBridge::GetInputLocale() { + DCHECK(host_); + return host_->GetInputLocale(); } base::i18n::TextDirection InputMethodBridge::GetInputTextDirection() { + DCHECK(host_); + return host_->GetInputTextDirection(); } bool InputMethodBridge::IsActive() { + DCHECK(host_); + return host_->IsActive(); } bool InputMethodBridge::IsCandidatePopupOpen() const { + DCHECK(host_); + return host_->IsCandidatePopupOpen(); } diff --git a/ui/views/ime/input_method_bridge.h b/ui/views/ime/input_method_bridge.h index 6e89946..0b26fd0 100644 --- a/ui/views/ime/input_method_bridge.h +++ b/ui/views/ime/input_method_bridge.h @@ -84,9 +84,15 @@ class InputMethodBridge : public InputMethodBase, ui::InputMethod* GetHostInputMethod() const; private: + class HostObserver; + void UpdateViewFocusState(); - ui::InputMethod* const host_; + ui::InputMethod* host_; + + // An observer observing the host input method for cases that the host input + // method is destroyed before this bridge input method. + scoped_ptr<HostObserver> host_observer_; const bool shared_input_method_; |