| Index: ui/views/ime/input_method_bridge.cc | 
| diff --git a/ui/views/ime/input_method_bridge.cc b/ui/views/ime/input_method_bridge.cc | 
| index 5238313031e9dbb703c69df4408f611b050f4126..ea13bd481707e2f7cb6569ebf31c128ed8ab4a1d 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(); | 
| } | 
|  | 
|  |