| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/chromeos/input_method/ibus_controller_impl.h" | 5 #include "chrome/browser/chromeos/input_method/ibus_controller_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> // for std::reverse. | 7 #include <algorithm> // for std::reverse. |
| 8 #include <cstdio> | 8 #include <cstdio> |
| 9 #include <cstring> // for std::strcmp. | 9 #include <cstring> // for std::strcmp. |
| 10 #include <set> | 10 #include <set> |
| 11 #include <sstream> | 11 #include <sstream> |
| 12 #include <stack> | 12 #include <stack> |
| 13 #include <utility> | 13 #include <utility> |
| 14 | 14 |
| 15 #include "ash/shell.h" | 15 #include "ash/shell.h" |
| 16 #include "base/bind.h" | 16 #include "base/bind.h" |
| 17 #include "base/environment.h" | 17 #include "base/environment.h" |
| 18 #include "base/files/file_path_watcher.h" | 18 #include "base/files/file_path_watcher.h" |
| 19 #include "base/memory/scoped_ptr.h" | 19 #include "base/memory/scoped_ptr.h" |
| 20 #include "base/message_loop.h" | 20 #include "base/message_loop.h" |
| 21 #include "base/rand_util.h" | 21 #include "base/rand_util.h" |
| 22 #include "base/sequenced_task_runner.h" | |
| 23 #include "base/string_split.h" | 22 #include "base/string_split.h" |
| 24 #include "base/stringprintf.h" | 23 #include "base/stringprintf.h" |
| 25 #include "chrome/browser/chromeos/input_method/input_method_config.h" | 24 #include "chrome/browser/chromeos/input_method/input_method_config.h" |
| 26 #include "chrome/browser/chromeos/input_method/input_method_property.h" | 25 #include "chrome/browser/chromeos/input_method/input_method_property.h" |
| 27 #include "chrome/browser/chromeos/input_method/input_method_util.h" | 26 #include "chrome/browser/chromeos/input_method/input_method_util.h" |
| 28 #include "chromeos/dbus/dbus_thread_manager.h" | 27 #include "chromeos/dbus/dbus_thread_manager.h" |
| 29 #include "chromeos/dbus/ibus/ibus_client.h" | 28 #include "chromeos/dbus/ibus/ibus_client.h" |
| 30 #include "chromeos/dbus/ibus/ibus_config_client.h" | 29 #include "chromeos/dbus/ibus/ibus_config_client.h" |
| 31 #include "chromeos/dbus/ibus/ibus_constants.h" | 30 #include "chromeos/dbus/ibus/ibus_constants.h" |
| 32 #include "chromeos/dbus/ibus/ibus_input_context_client.h" | 31 #include "chromeos/dbus/ibus/ibus_input_context_client.h" |
| 33 #include "chromeos/dbus/ibus/ibus_panel_service.h" | 32 #include "chromeos/dbus/ibus/ibus_panel_service.h" |
| 34 #include "chromeos/dbus/ibus/ibus_property.h" | 33 #include "chromeos/dbus/ibus/ibus_property.h" |
| 34 #include "content/public/browser/browser_thread.h" |
| 35 #include "ui/aura/client/aura_constants.h" | 35 #include "ui/aura/client/aura_constants.h" |
| 36 #include "ui/aura/root_window.h" | 36 #include "ui/aura/root_window.h" |
| 37 #include "ui/base/ime/input_method_ibus.h" | 37 #include "ui/base/ime/input_method_ibus.h" |
| 38 | 38 |
| 39 namespace { | 39 namespace { |
| 40 | 40 |
| 41 // Finds a property which has |new_prop.key| from |prop_list|, and replaces the | 41 // Finds a property which has |new_prop.key| from |prop_list|, and replaces the |
| 42 // property with |new_prop|. Returns true if such a property is found. | 42 // property with |new_prop|. Returns true if such a property is found. |
| 43 bool FindAndUpdateProperty( | 43 bool FindAndUpdateProperty( |
| 44 const chromeos::input_method::InputMethodProperty& new_prop, | 44 const chromeos::input_method::InputMethodProperty& new_prop, |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 return result; | 186 return result; |
| 187 } | 187 } |
| 188 | 188 |
| 189 class IBusAddressWatcher { | 189 class IBusAddressWatcher { |
| 190 public: | 190 public: |
| 191 class IBusAddressFileWatcherDelegate | 191 class IBusAddressFileWatcherDelegate |
| 192 : public base::files::FilePathWatcher::Delegate { | 192 : public base::files::FilePathWatcher::Delegate { |
| 193 public: | 193 public: |
| 194 IBusAddressFileWatcherDelegate( | 194 IBusAddressFileWatcherDelegate( |
| 195 const std::string& ibus_address, | 195 const std::string& ibus_address, |
| 196 const base::Callback<void(const std::string&)>& callback, | 196 IBusControllerImpl* controller, |
| 197 IBusAddressWatcher* watcher) | 197 IBusAddressWatcher* watcher) |
| 198 : ibus_address_(ibus_address), | 198 : ibus_address_(ibus_address), |
| 199 callback_(callback), | 199 controller_(controller), |
| 200 watcher_(watcher) { | 200 watcher_(watcher) { |
| 201 DCHECK(watcher); | 201 DCHECK(watcher); |
| 202 DCHECK(!ibus_address.empty()); | 202 DCHECK(!ibus_address.empty()); |
| 203 } | 203 } |
| 204 | 204 |
| 205 virtual void OnFilePathChanged(const FilePath& file_path) OVERRIDE { | 205 virtual void OnFilePathChanged(const FilePath& file_path) OVERRIDE { |
| 206 if (!watcher_->IsWatching()) | 206 if (!watcher_->IsWatching()) |
| 207 return; | 207 return; |
| 208 callback_.Run(ibus_address_); | 208 bool success = content::BrowserThread::PostTask( |
| 209 content::BrowserThread::UI, |
| 210 FROM_HERE, |
| 211 base::Bind( |
| 212 &IBusControllerImpl::IBusDaemonInitializationDone, |
| 213 controller_, |
| 214 ibus_address_)); |
| 215 DCHECK(success); |
| 209 watcher_->StopSoon(); | 216 watcher_->StopSoon(); |
| 210 } | 217 } |
| 211 | 218 |
| 212 protected: | 219 protected: |
| 213 virtual ~IBusAddressFileWatcherDelegate() {} | 220 virtual ~IBusAddressFileWatcherDelegate() {} |
| 214 | 221 |
| 215 private: | 222 private: |
| 216 // The ibus-daemon address. | 223 // The ibus-daemon address. |
| 217 const std::string ibus_address_; | 224 const std::string ibus_address_; |
| 218 base::Callback<void(const std::string&)> callback_; | 225 IBusControllerImpl* controller_; |
| 219 IBusAddressWatcher* watcher_; | 226 IBusAddressWatcher* watcher_; |
| 220 | 227 |
| 221 DISALLOW_COPY_AND_ASSIGN(IBusAddressFileWatcherDelegate); | 228 DISALLOW_COPY_AND_ASSIGN(IBusAddressFileWatcherDelegate); |
| 222 }; | 229 }; |
| 223 | 230 |
| 224 static void Start(const std::string& ibus_address, | 231 static void Start(const std::string& ibus_address, |
| 225 const base::Callback<void(const std::string&)>& callback) { | 232 IBusControllerImpl* controller) { |
| 226 IBusAddressWatcher* instance = IBusAddressWatcher::Get(); | 233 IBusAddressWatcher* instance = IBusAddressWatcher::Get(); |
| 227 scoped_ptr<base::Environment> env(base::Environment::Create()); | 234 scoped_ptr<base::Environment> env(base::Environment::Create()); |
| 228 std::string address_file_path; | 235 std::string address_file_path; |
| 229 // TODO(nona): move reading environment variables to UI thread. | 236 // TODO(nona): move reading environment variables to UI thread. |
| 230 env->GetVar("IBUS_ADDRESS_FILE", &address_file_path); | 237 env->GetVar("IBUS_ADDRESS_FILE", &address_file_path); |
| 231 DCHECK(!address_file_path.empty()); | 238 DCHECK(!address_file_path.empty()); |
| 232 | 239 |
| 233 if (instance->IsWatching()) | 240 if (instance->IsWatching()) |
| 234 instance->StopNow(); | 241 instance->StopNow(); |
| 235 instance->watcher_ = new base::files::FilePathWatcher; | 242 instance->watcher_ = new base::files::FilePathWatcher; |
| 236 | 243 |
| 237 // The |delegate| is owned by watcher. | 244 // The |delegate| is owned by watcher. |
| 238 IBusAddressFileWatcherDelegate* delegate = | 245 IBusAddressFileWatcherDelegate* delegate = |
| 239 new IBusAddressFileWatcherDelegate(ibus_address, callback, instance); | 246 new IBusAddressFileWatcherDelegate(ibus_address, controller, instance); |
| 240 bool result = instance->watcher_->Watch(FilePath(address_file_path), | 247 bool result = instance->watcher_->Watch(FilePath(address_file_path), |
| 241 delegate); | 248 delegate); |
| 242 DCHECK(result); | 249 DCHECK(result); |
| 243 } | 250 } |
| 244 | 251 |
| 245 void StopNow() { | 252 void StopNow() { |
| 246 delete watcher_; | 253 delete watcher_; |
| 247 watcher_ = NULL; | 254 watcher_ = NULL; |
| 248 } | 255 } |
| 249 | 256 |
| 250 void StopSoon() { | 257 void StopSoon() { |
| 251 if (!watcher_) | 258 if (!watcher_) |
| 252 return; | 259 return; |
| 253 MessageLoop::current()->DeleteSoon(FROM_HERE, watcher_); | 260 MessageLoop::current()->DeleteSoon(FROM_HERE, watcher_); |
| 254 watcher_ = NULL; | 261 watcher_ = NULL; |
| 255 } | 262 } |
| 256 | 263 |
| 257 bool IsWatching() const { | 264 bool IsWatching() const { |
| 258 return watcher_ != NULL; | 265 return watcher_ != NULL; |
| 259 } | 266 } |
| 260 | 267 |
| 261 private: | 268 private: |
| 262 static IBusAddressWatcher* Get() { | 269 static IBusAddressWatcher* Get() { |
| 263 static IBusAddressWatcher* instance = new IBusAddressWatcher; | 270 static IBusAddressWatcher* instance = new IBusAddressWatcher; |
| 271 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
| 264 return instance; | 272 return instance; |
| 265 } | 273 } |
| 266 | 274 |
| 267 // Singleton | 275 // Singleton |
| 268 IBusAddressWatcher() | 276 IBusAddressWatcher() |
| 269 : watcher_(NULL) {} | 277 : watcher_(NULL) {} |
| 270 base::files::FilePathWatcher* watcher_; | 278 base::files::FilePathWatcher* watcher_; |
| 271 | 279 |
| 272 DISALLOW_COPY_AND_ASSIGN(IBusAddressWatcher); | 280 DISALLOW_COPY_AND_ASSIGN(IBusAddressWatcher); |
| 273 }; | 281 }; |
| 274 | 282 |
| 275 } // namespace | 283 } // namespace |
| 276 | 284 |
| 277 IBusControllerImpl::IBusControllerImpl( | 285 IBusControllerImpl::IBusControllerImpl() |
| 278 const scoped_refptr<base::SequencedTaskRunner>& default_task_runner, | |
| 279 const scoped_refptr<base::SequencedTaskRunner>& worker_task_runner) | |
| 280 : process_handle_(base::kNullProcessHandle), | 286 : process_handle_(base::kNullProcessHandle), |
| 281 ibus_daemon_status_(IBUS_DAEMON_STOP), | 287 ibus_daemon_status_(IBUS_DAEMON_STOP), |
| 282 input_method_(NULL), | 288 input_method_(NULL), |
| 283 default_task_runner_(default_task_runner), | |
| 284 worker_task_runner_(worker_task_runner), | |
| 285 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | 289 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| 286 } | 290 } |
| 287 | 291 |
| 288 IBusControllerImpl::~IBusControllerImpl() { | 292 IBusControllerImpl::~IBusControllerImpl() { |
| 289 } | 293 } |
| 290 | 294 |
| 291 bool IBusControllerImpl::Start() { | 295 bool IBusControllerImpl::Start() { |
| 292 if (IBusConnectionsAreAlive()) | 296 if (IBusConnectionsAreAlive()) |
| 293 return true; | 297 return true; |
| 294 if (ibus_daemon_status_ == IBUS_DAEMON_STOP || | 298 if (ibus_daemon_status_ == IBUS_DAEMON_STOP || |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 } | 494 } |
| 491 | 495 |
| 492 ibus_daemon_status_ = IBUS_DAEMON_INITIALIZING; | 496 ibus_daemon_status_ = IBUS_DAEMON_INITIALIZING; |
| 493 ibus_daemon_address_ = base::StringPrintf( | 497 ibus_daemon_address_ = base::StringPrintf( |
| 494 "unix:abstract=ibus-%d", | 498 "unix:abstract=ibus-%d", |
| 495 base::RandInt(0, std::numeric_limits<int>::max())); | 499 base::RandInt(0, std::numeric_limits<int>::max())); |
| 496 | 500 |
| 497 // Set up ibus-daemon address file watcher before launching ibus-daemon, | 501 // Set up ibus-daemon address file watcher before launching ibus-daemon, |
| 498 // because if watcher starts after ibus-daemon, we may miss the ibus | 502 // because if watcher starts after ibus-daemon, we may miss the ibus |
| 499 // connection initialization. | 503 // connection initialization. |
| 500 | 504 bool success = content::BrowserThread::PostTaskAndReply( |
| 501 // Create a callback to bounce from the worker thread to the default thread. | 505 content::BrowserThread::FILE, |
| 502 base::Callback<void(const std::string&)> callback(base::Bind( | |
| 503 &IBusControllerImpl::IBusDaemonInitializationDoneWorkerCallback, | |
| 504 weak_ptr_factory_.GetWeakPtr())); | |
| 505 | |
| 506 bool success = worker_task_runner_->PostTaskAndReply( | |
| 507 FROM_HERE, | 506 FROM_HERE, |
| 508 base::Bind(&IBusAddressWatcher::Start, ibus_daemon_address_, callback), | 507 base::Bind(&IBusAddressWatcher::Start, |
| 508 ibus_daemon_address_, |
| 509 base::Unretained(this)), |
| 509 base::Bind(&IBusControllerImpl::LaunchIBusDaemon, | 510 base::Bind(&IBusControllerImpl::LaunchIBusDaemon, |
| 510 weak_ptr_factory_.GetWeakPtr(), | 511 weak_ptr_factory_.GetWeakPtr(), |
| 511 ibus_daemon_address_)); | 512 ibus_daemon_address_)); |
| 512 DCHECK(success); | 513 DCHECK(success); |
| 513 return true; | 514 return true; |
| 514 } | 515 } |
| 515 | 516 |
| 516 void IBusControllerImpl::LaunchIBusDaemon(const std::string& ibus_address) { | 517 void IBusControllerImpl::LaunchIBusDaemon(const std::string& ibus_address) { |
| 517 DCHECK_EQ(base::kNullProcessHandle, process_handle_); | 518 DCHECK_EQ(base::kNullProcessHandle, process_handle_); |
| 518 static const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon"; | 519 static const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon"; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 } | 567 } |
| 567 | 568 |
| 568 void IBusControllerImpl::OnIBusConfigClientInitialized() { | 569 void IBusControllerImpl::OnIBusConfigClientInitialized() { |
| 569 InputMethodConfigRequests::const_iterator iter = | 570 InputMethodConfigRequests::const_iterator iter = |
| 570 current_config_values_.begin(); | 571 current_config_values_.begin(); |
| 571 for (; iter != current_config_values_.end(); ++iter) { | 572 for (; iter != current_config_values_.end(); ++iter) { |
| 572 SetInputMethodConfigInternal(iter->first, iter->second); | 573 SetInputMethodConfigInternal(iter->first, iter->second); |
| 573 } | 574 } |
| 574 } | 575 } |
| 575 | 576 |
| 576 void IBusControllerImpl::IBusDaemonInitializationDoneWorkerCallback( | 577 // static |
| 578 void IBusControllerImpl::IBusDaemonInitializationDone( |
| 579 IBusControllerImpl* controller, |
| 577 const std::string& ibus_address) { | 580 const std::string& ibus_address) { |
| 578 bool result = default_task_runner_->PostTask(FROM_HERE, base::Bind( | 581 if (controller->ibus_daemon_address_ != ibus_address) |
| 579 &IBusControllerImpl::IBusDaemonInitializationDone, | |
| 580 weak_ptr_factory_.GetWeakPtr(), | |
| 581 ibus_address)); | |
| 582 DCHECK(result); | |
| 583 } | |
| 584 | |
| 585 void IBusControllerImpl::IBusDaemonInitializationDone( | |
| 586 const std::string& ibus_address) { | |
| 587 if (ibus_daemon_address_ != ibus_address) | |
| 588 return; | 582 return; |
| 589 | 583 |
| 590 if (ibus_daemon_status_ != IBUS_DAEMON_INITIALIZING) { | 584 if (controller->ibus_daemon_status_ != IBUS_DAEMON_INITIALIZING) { |
| 591 // Stop() or OnIBusDaemonExit() has already been called. | 585 // Stop() or OnIBusDaemonExit() has already been called. |
| 592 return; | 586 return; |
| 593 } | 587 } |
| 594 chromeos::DBusThreadManager::Get()->InitIBusBus(ibus_address); | 588 chromeos::DBusThreadManager::Get()->InitIBusBus(ibus_address); |
| 595 ibus_daemon_status_ = IBUS_DAEMON_RUNNING; | 589 controller->ibus_daemon_status_ = IBUS_DAEMON_RUNNING; |
| 596 | 590 |
| 597 ui::InputMethodIBus* input_method_ibus = GetInputMethod(); | 591 ui::InputMethodIBus* input_method_ibus = controller->GetInputMethod(); |
| 598 DCHECK(input_method_ibus); | 592 DCHECK(input_method_ibus); |
| 599 input_method_ibus->OnConnected(); | 593 input_method_ibus->OnConnected(); |
| 600 | 594 |
| 601 DBusThreadManager::Get()->GetIBusPanelService()->SetUpPropertyHandler(this); | 595 DBusThreadManager::Get()->GetIBusPanelService()->SetUpPropertyHandler( |
| 596 controller); |
| 602 | 597 |
| 603 // Restore previous input method at the beggining of connection. | 598 // Restore previous input method at the beggining of connection. |
| 604 if (!current_input_method_id_.empty()) | 599 if (!controller->current_input_method_id_.empty()) { |
| 605 SendChangeInputMethodRequest(current_input_method_id_); | 600 controller->SendChangeInputMethodRequest( |
| 601 controller->current_input_method_id_); |
| 602 } |
| 606 | 603 |
| 607 DBusThreadManager::Get()->GetIBusConfigClient()->InitializeAsync( | 604 DBusThreadManager::Get()->GetIBusConfigClient()->InitializeAsync( |
| 608 base::Bind(&IBusControllerImpl::OnIBusConfigClientInitialized, | 605 base::Bind(&IBusControllerImpl::OnIBusConfigClientInitialized, |
| 609 weak_ptr_factory_.GetWeakPtr())); | 606 controller->weak_ptr_factory_.GetWeakPtr())); |
| 610 | 607 |
| 611 FOR_EACH_OBSERVER(Observer, observers_, OnConnected()); | 608 FOR_EACH_OBSERVER(Observer, controller->observers_, OnConnected()); |
| 612 | 609 |
| 613 VLOG(1) << "The ibus-daemon initialization is done."; | 610 VLOG(1) << "The ibus-daemon initialization is done."; |
| 614 } | 611 } |
| 615 | 612 |
| 616 // static | 613 // static |
| 617 void IBusControllerImpl::OnIBusDaemonExit(GPid pid, | 614 void IBusControllerImpl::OnIBusDaemonExit(GPid pid, |
| 618 gint status, | 615 gint status, |
| 619 IBusControllerImpl* controller) { | 616 IBusControllerImpl* controller) { |
| 620 if (controller->process_handle_ != base::kNullProcessHandle) { | 617 if (controller->process_handle_ != base::kNullProcessHandle) { |
| 621 if (base::GetProcId(controller->process_handle_) == pid) { | 618 if (base::GetProcId(controller->process_handle_) == pid) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 652 | 649 |
| 653 // static | 650 // static |
| 654 bool IBusControllerImpl::FindAndUpdatePropertyForTesting( | 651 bool IBusControllerImpl::FindAndUpdatePropertyForTesting( |
| 655 const chromeos::input_method::InputMethodProperty& new_prop, | 652 const chromeos::input_method::InputMethodProperty& new_prop, |
| 656 chromeos::input_method::InputMethodPropertyList* prop_list) { | 653 chromeos::input_method::InputMethodPropertyList* prop_list) { |
| 657 return FindAndUpdateProperty(new_prop, prop_list); | 654 return FindAndUpdateProperty(new_prop, prop_list); |
| 658 } | 655 } |
| 659 | 656 |
| 660 } // namespace input_method | 657 } // namespace input_method |
| 661 } // namespace chromeos | 658 } // namespace chromeos |
| OLD | NEW |