Index: ui/base/ime/input_method_ibus.cc |
diff --git a/ui/base/ime/input_method_ibus.cc b/ui/base/ime/input_method_ibus.cc |
index 7fd48b2db3c1e38067397b6cdba8d9ace72d3b04..d3d81a44a4167c5cd766d82a7bbd93af34db96b5 100644 |
--- a/ui/base/ime/input_method_ibus.cc |
+++ b/ui/base/ime/input_method_ibus.cc |
@@ -38,6 +38,7 @@ namespace { |
const int kIBusReleaseMask = 1 << 30; |
const char kClientName[] = "chrome"; |
+const int kMaxRetryCount = 10; |
// Following capability mask is introduced from |
// http://ibus.googlecode.com/svn/docs/ibus-1.4/ibus-ibustypes.html#IBusCapabilite |
@@ -162,69 +163,12 @@ void InputMethodIBus::PendingKeyEvent::ProcessPostIME(bool handled) { |
// and 'unmodified_character_' to support i18n VKs like a French VK! |
} |
-// A class to hold information of a pending request for creating an ibus input |
-// context. |
-class InputMethodIBus::PendingCreateICRequest { |
- public: |
- PendingCreateICRequest(InputMethodIBus* input_method, |
- PendingCreateICRequest** request_ptr); |
- virtual ~PendingCreateICRequest(); |
- |
- // Set up signal handlers, or destroy object proxy if the input context is |
- // already abandoned. |
- void InitOrAbandonInputContext(); |
- |
- // Called if the create input context method call is failed. |
- void OnCreateInputContextFailed(); |
- |
- // Abandon this pending key event. Its result will just be discarded. |
- void Abandon() { |
- input_method_ = NULL; |
- request_ptr_ = NULL; |
- // Do not reset |ibus_client_| here. |
- } |
- |
- private: |
- InputMethodIBus* input_method_; |
- PendingCreateICRequest** request_ptr_; |
- |
- DISALLOW_COPY_AND_ASSIGN(PendingCreateICRequest); |
-}; |
- |
-InputMethodIBus::PendingCreateICRequest::PendingCreateICRequest( |
- InputMethodIBus* input_method, |
- PendingCreateICRequest** request_ptr) |
- : input_method_(input_method), |
- request_ptr_(request_ptr) { |
-} |
- |
-InputMethodIBus::PendingCreateICRequest::~PendingCreateICRequest() { |
- if (request_ptr_) { |
- DCHECK_EQ(*request_ptr_, this); |
- *request_ptr_ = NULL; |
- } |
-} |
- |
-void InputMethodIBus::PendingCreateICRequest::OnCreateInputContextFailed() { |
- // TODO(nona): If the connection between Chrome and ibus-daemon terminates |
- // for some reason, the create ic request will fail. We might want to call |
- // ibus_client_->CreateContext() again after some delay. |
-} |
- |
-void InputMethodIBus::PendingCreateICRequest::InitOrAbandonInputContext() { |
- if (input_method_) { |
- DCHECK(input_method_->IsContextReady()); |
- input_method_->SetUpSignalHandlers(); |
- } else { |
- GetInputContextClient()->ResetObjectProxy(); |
- } |
-} |
- |
// InputMethodIBus implementation ----------------------------------------- |
InputMethodIBus::InputMethodIBus( |
internal::InputMethodDelegate* delegate) |
: ibus_client_(new internal::IBusClient), |
- pending_create_ic_request_(NULL), |
+ input_context_state_(INPUT_CONTEXT_STOP), |
+ create_input_context_fail_count_(0), |
context_focused_(false), |
composing_text_(false), |
composition_changed_(false), |
@@ -423,20 +367,23 @@ void InputMethodIBus::OnDidChangeFocusedClient(TextInputClient* focused_before, |
void InputMethodIBus::CreateContext() { |
DCHECK(IsConnected()); |
- DCHECK(!pending_create_ic_request_); |
- pending_create_ic_request_ = new PendingCreateICRequest( |
- this, &pending_create_ic_request_); |
+ if (input_context_state_ != INPUT_CONTEXT_STOP) { |
+ DVLOG(1) << "Input context is already created or waiting ibus-daemon" |
+ " response."; |
+ return; |
+ } |
+ |
+ input_context_state_ = INPUT_CONTEXT_WAIT_CREATE_INPUT_CONTEXT_RESPONSE; |
// Creates the input context asynchronously. |
+ DCHECK(!IsContextReady()); |
chromeos::DBusThreadManager::Get()->GetIBusClient()->CreateInputContext( |
kClientName, |
base::Bind(&InputMethodIBus::CreateInputContextDone, |
- weak_ptr_factory_.GetWeakPtr(), |
- base::Unretained(pending_create_ic_request_)), |
+ weak_ptr_factory_.GetWeakPtr()), |
base::Bind(&InputMethodIBus::CreateInputContextFail, |
- weak_ptr_factory_.GetWeakPtr(), |
- base::Unretained(pending_create_ic_request_))); |
+ weak_ptr_factory_.GetWeakPtr())); |
} |
void InputMethodIBus::SetUpSignalHandlers() { |
@@ -478,13 +425,9 @@ void InputMethodIBus::SetUpSignalHandlers() { |
} |
void InputMethodIBus::DestroyContext() { |
- if (pending_create_ic_request_) { |
- DCHECK(!IsContextReady()); |
- // |pending_create_ic_request_| will be deleted in CreateInputContextDone(). |
- pending_create_ic_request_->Abandon(); |
- pending_create_ic_request_ = NULL; |
+ if (input_context_state_ == INPUT_CONTEXT_STOP) |
return; |
- } |
+ input_context_state_ = INPUT_CONTEXT_STOP; |
const chromeos::IBusInputContextClient* input_context = |
chromeos::DBusThreadManager::Get()->GetIBusInputContextClient(); |
if (input_context && input_context->IsObjectProxyReady()) { |
@@ -906,19 +849,46 @@ void InputMethodIBus::ResetInputContext() { |
} |
void InputMethodIBus::CreateInputContextDone( |
- PendingCreateICRequest* ic_request, |
const dbus::ObjectPath& object_path) { |
+ DCHECK_NE(INPUT_CONTEXT_RUNNING, input_context_state_); |
+ |
+ if (input_context_state_ == INPUT_CONTEXT_STOP) { |
+ // DestroyContext has already been called. |
+ return; |
+ } |
+ |
chromeos::DBusThreadManager::Get()->GetIBusInputContextClient() |
->Initialize(chromeos::DBusThreadManager::Get()->GetIBusBus(), |
object_path); |
- ic_request->InitOrAbandonInputContext(); |
- delete ic_request; |
+ |
+ input_context_state_ = INPUT_CONTEXT_RUNNING; |
+ DCHECK(IsContextReady()); |
+ SetUpSignalHandlers(); |
} |
-void InputMethodIBus::CreateInputContextFail( |
- PendingCreateICRequest* ic_request) { |
- ic_request->OnCreateInputContextFailed(); |
- delete ic_request; |
+void InputMethodIBus::CreateInputContextFail() { |
+ DCHECK_NE(INPUT_CONTEXT_RUNNING, input_context_state_); |
+ if (input_context_state_ == INPUT_CONTEXT_STOP) { |
+ // CreateInputContext failed but the input context is no longer |
+ // necessary, thus do nothing. |
+ return; |
+ } |
+ |
+ if (++create_input_context_fail_count_ >= kMaxRetryCount) { |
+ DVLOG(1) << "CreateInputContext failed even tried " |
+ << kMaxRetryCount << " times, give up."; |
+ create_input_context_fail_count_ = 0; |
+ input_context_state_ = INPUT_CONTEXT_STOP; |
+ return; |
+ } |
+ |
+ // Try CreateInputContext again. |
+ chromeos::DBusThreadManager::Get()->GetIBusClient()->CreateInputContext( |
+ kClientName, |
+ base::Bind(&InputMethodIBus::CreateInputContextDone, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&InputMethodIBus::CreateInputContextFail, |
+ weak_ptr_factory_.GetWeakPtr())); |
} |
bool InputMethodIBus::IsConnected() { |