Chromium Code Reviews| 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 "base/bind.h" | |
| 16 #include "base/environment.h" | |
| 17 #include "base/files/file_path_watcher.h" | |
| 15 #include "base/memory/scoped_ptr.h" | 18 #include "base/memory/scoped_ptr.h" |
| 19 #include "base/message_loop.h" | |
| 20 #include "base/rand_util.h" | |
| 16 #include "base/stringprintf.h" | 21 #include "base/stringprintf.h" |
| 17 #include "base/string_split.h" | 22 #include "base/string_split.h" |
| 18 #include "chrome/browser/chromeos/input_method/input_method_config.h" | 23 #include "chrome/browser/chromeos/input_method/input_method_config.h" |
| 19 #include "chrome/browser/chromeos/input_method/input_method_property.h" | 24 #include "chrome/browser/chromeos/input_method/input_method_property.h" |
| 20 #include "chrome/browser/chromeos/input_method/input_method_util.h" | 25 #include "chrome/browser/chromeos/input_method/input_method_util.h" |
| 26 #include "chromeos/dbus/dbus_thread_manager.h" | |
| 27 #include "content/public/browser/browser_thread.h" | |
| 21 | 28 |
| 22 // TODO(nona): Remove libibus dependency from this file. Then, write unit tests | 29 // TODO(nona): Remove libibus dependency from this file. Then, write unit tests |
| 23 // for all functions in this file. crbug.com/26334 | 30 // for all functions in this file. crbug.com/26334 |
| 24 #if defined(HAVE_IBUS) | 31 #if defined(HAVE_IBUS) |
| 25 #include <ibus.h> | 32 #include <ibus.h> |
| 26 #endif | 33 #endif |
| 27 | 34 |
| 28 namespace { | 35 namespace { |
| 29 | 36 |
| 30 // Finds a property which has |new_prop.key| from |prop_list|, and replaces the | 37 // Finds a property which has |new_prop.key| from |prop_list|, and replaces the |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 350 std::stringstream stream; | 357 std::stringstream stream; |
| 351 for (int i = 0;; ++i) { | 358 for (int i = 0;; ++i) { |
| 352 IBusProperty* prop = ibus_prop_list_get(prop_list, i); | 359 IBusProperty* prop = ibus_prop_list_get(prop_list, i); |
| 353 if (!prop) | 360 if (!prop) |
| 354 break; | 361 break; |
| 355 stream << PrintProp(prop, tree_level); | 362 stream << PrintProp(prop, tree_level); |
| 356 } | 363 } |
| 357 return stream.str(); | 364 return stream.str(); |
| 358 } | 365 } |
| 359 | 366 |
| 367 // The implementation of FilePathWatcher::Delegate, used in | |
| 368 // StartAddressFileWatch function. | |
| 369 class IBusAddressFileWatcherDelegate | |
| 370 : public base::files::FilePathWatcher::Delegate { | |
| 371 public: | |
| 372 IBusAddressFileWatcherDelegate(const std::string& ibus_address, | |
| 373 base::files::FilePathWatcher* watcher) | |
| 374 : ibus_address_(ibus_address), | |
| 375 watcher_(watcher) { | |
| 376 } | |
| 377 | |
| 378 virtual ~IBusAddressFileWatcherDelegate() {} | |
| 379 | |
| 380 virtual void OnFilePathChanged(const FilePath& file_path) { | |
| 381 content::BrowserThread::PostTask( | |
| 382 content::BrowserThread::UI, | |
| 383 FROM_HERE, | |
| 384 base::Bind(&chromeos::DBusThreadManager::MaybeResetIBusBus, | |
| 385 base::Unretained(chromeos::DBusThreadManager::Get()), | |
| 386 ibus_address_)); | |
| 387 MessageLoop::current()->DeleteSoon(FROM_HERE, watcher_); | |
| 388 } | |
| 389 | |
| 390 private: | |
| 391 | |
|
Yusuke Sato
2012/04/26 00:46:28
nit: remove
Seigo Nonaka
2012/04/26 17:40:59
Done.
| |
| 392 // The ibus-daemon address. | |
| 393 std::string ibus_address_; | |
|
Yusuke Sato
2012/04/26 00:46:28
nit: const std::string would be better.
Seigo Nonaka
2012/04/26 17:40:59
Done.
| |
| 394 | |
| 395 base::files::FilePathWatcher* watcher_; | |
|
Yusuke Sato
2012/04/26 00:46:28
nit: vertical space after this line.
Seigo Nonaka
2012/04/26 17:40:59
Done.
| |
| 396 DISALLOW_COPY_AND_ASSIGN(IBusAddressFileWatcherDelegate); | |
| 397 }; | |
| 398 | |
| 399 void StartAddressFileWatch(const std::string& ibus_address) { | |
| 400 scoped_ptr<base::Environment> env(base::Environment::Create()); | |
| 401 std::string address_file_path; | |
| 402 env->GetVar("IBUS_ADDRESS_FILE", &address_file_path); | |
| 403 | |
| 404 // The |watcher| instance will be released by |delegate|. | |
| 405 base::files::FilePathWatcher* watcher = new base::files::FilePathWatcher(); | |
|
Yusuke Sato
2012/04/26 00:46:28
nit: you can omit '()'.
Seigo Nonaka
2012/04/26 17:40:59
Done.
| |
| 406 | |
| 407 // The |delegate| is owned by watcher. | |
| 408 IBusAddressFileWatcherDelegate* delegate = new IBusAddressFileWatcherDelegate( | |
| 409 ibus_address, watcher); | |
| 410 bool result = watcher->Watch(FilePath(address_file_path), delegate); | |
| 411 DCHECK(result); | |
| 412 } | |
| 360 } // namespace | 413 } // namespace |
| 361 | 414 |
| 362 IBusControllerImpl::IBusControllerImpl() | 415 IBusControllerImpl::IBusControllerImpl() |
| 363 : ibus_(NULL), | 416 : ibus_(NULL), |
| 364 ibus_config_(NULL), | 417 ibus_config_(NULL), |
| 365 should_launch_daemon_(false), | 418 should_launch_daemon_(false), |
| 366 process_handle_(base::kNullProcessHandle) { | 419 process_handle_(base::kNullProcessHandle), |
| 420 weak_ptr_factory_(this) { | |
|
Yusuke Sato
2012/04/26 00:46:28
ALLOW_THIS_IN_INITIALIZER_LIST?
Seigo Nonaka
2012/04/26 17:40:59
Done.
| |
| 367 } | 421 } |
| 368 | 422 |
| 369 IBusControllerImpl::~IBusControllerImpl() { | 423 IBusControllerImpl::~IBusControllerImpl() { |
| 370 // Disconnect signals so the handler functions will not be called with | 424 // Disconnect signals so the handler functions will not be called with |
| 371 // |this| which is already freed. | 425 // |this| which is already freed. |
| 372 if (ibus_) { | 426 if (ibus_) { |
| 373 g_signal_handlers_disconnect_by_func( | 427 g_signal_handlers_disconnect_by_func( |
| 374 ibus_, | 428 ibus_, |
| 375 reinterpret_cast<gpointer>(G_CALLBACK(BusConnectedThunk)), | 429 reinterpret_cast<gpointer>(G_CALLBACK(BusConnectedThunk)), |
| 376 this); | 430 this); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 401 this); | 455 this); |
| 402 } | 456 } |
| 403 } | 457 } |
| 404 } | 458 } |
| 405 | 459 |
| 406 bool IBusControllerImpl::Start() { | 460 bool IBusControllerImpl::Start() { |
| 407 MaybeInitializeIBusBus(); | 461 MaybeInitializeIBusBus(); |
| 408 should_launch_daemon_ = true; | 462 should_launch_daemon_ = true; |
| 409 if (IBusConnectionsAreAlive()) | 463 if (IBusConnectionsAreAlive()) |
| 410 return true; | 464 return true; |
| 465 | |
|
Yusuke Sato
2012/04/26 00:46:28
nit: remove
Seigo Nonaka
2012/04/26 17:40:59
Done.
| |
| 411 return MaybeLaunchIBusDaemon(); | 466 return MaybeLaunchIBusDaemon(); |
| 412 } | 467 } |
| 413 | 468 |
| 414 void IBusControllerImpl::Reset() { | 469 void IBusControllerImpl::Reset() { |
| 415 if (!IBusConnectionsAreAlive()) | 470 if (!IBusConnectionsAreAlive()) |
| 416 return; | 471 return; |
| 417 IBusInputContext* context = | 472 IBusInputContext* context = |
| 418 GetInputContext(current_input_context_path_, ibus_); | 473 GetInputContext(current_input_context_path_, ibus_); |
| 419 if (!context) | 474 if (!context) |
| 420 return; | 475 return; |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 886 // Notify the change. | 941 // Notify the change. |
| 887 if (!prop_list.empty()) { | 942 if (!prop_list.empty()) { |
| 888 for (size_t i = 0; i < prop_list.size(); ++i) { | 943 for (size_t i = 0; i < prop_list.size(); ++i) { |
| 889 FindAndUpdateProperty(prop_list[i], ¤t_property_list_); | 944 FindAndUpdateProperty(prop_list[i], ¤t_property_list_); |
| 890 } | 945 } |
| 891 FOR_EACH_OBSERVER(Observer, observers_, PropertyChanged()); | 946 FOR_EACH_OBSERVER(Observer, observers_, PropertyChanged()); |
| 892 } | 947 } |
| 893 } | 948 } |
| 894 | 949 |
| 895 bool IBusControllerImpl::MaybeLaunchIBusDaemon() { | 950 bool IBusControllerImpl::MaybeLaunchIBusDaemon() { |
| 896 static const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon"; | |
| 897 | |
| 898 if (process_handle_ != base::kNullProcessHandle) { | 951 if (process_handle_ != base::kNullProcessHandle) { |
| 899 DVLOG(1) << "MaybeLaunchIBusDaemon: ibus-daemon is already running."; | 952 DVLOG(1) << "MaybeLaunchIBusDaemon: ibus-daemon is already running."; |
| 900 return false; | 953 return false; |
| 901 } | 954 } |
| 902 if (!should_launch_daemon_) | 955 if (!should_launch_daemon_) |
| 903 return false; | 956 return false; |
| 904 | 957 |
| 958 std::string ibus_address = base::StringPrintf( | |
|
Yusuke Sato
2012/04/26 00:46:28
looks like this function still has a race conditio
Yusuke Sato
2012/04/26 00:46:28
const
Seigo Nonaka
2012/04/26 17:40:59
Done.
Seigo Nonaka
2012/04/26 17:40:59
I introduce is_initializing_ibus_daemon_ to avoid
| |
| 959 "unix:abstract=/tmp/ibus-%0lX", base::RandUint64()); | |
| 960 | |
| 961 // Set up ibus-daemon address file watcher before launching ibus-daemon, | |
| 962 // because if watcher start after ibus-daemon, we may miss the ibus connection | |
| 963 // initialization. | |
| 964 content::BrowserThread::PostTaskAndReply( | |
| 965 content::BrowserThread::FILE, | |
| 966 FROM_HERE, | |
| 967 base::Bind(&StartAddressFileWatch, ibus_address), | |
| 968 base::Bind(&IBusControllerImpl::LaunchIBusDaemon, | |
| 969 weak_ptr_factory_.GetWeakPtr(), | |
| 970 ibus_address)); | |
| 971 return true; | |
| 972 } | |
| 973 | |
| 974 void IBusControllerImpl::LaunchIBusDaemon(const std::string& ibus_address) { | |
| 975 static const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon"; | |
| 905 // TODO(zork): Send output to /var/log/ibus.log | 976 // TODO(zork): Send output to /var/log/ibus.log |
| 906 const std::string ibus_daemon_command_line = | 977 const std::string ibus_daemon_command_line = |
| 907 base::StringPrintf("%s --panel=disable --cache=none --restart --replace", | 978 base::StringPrintf("%s --panel=disable --cache=none --restart --replace" |
| 908 kIBusDaemonPath); | 979 " --address=%s", |
| 980 kIBusDaemonPath, | |
| 981 ibus_address.c_str()); | |
| 909 if (!LaunchProcess(ibus_daemon_command_line, | 982 if (!LaunchProcess(ibus_daemon_command_line, |
| 910 &process_handle_, | 983 &process_handle_, |
| 911 reinterpret_cast<GChildWatchFunc>(OnIBusDaemonExit))) { | 984 reinterpret_cast<GChildWatchFunc>(OnIBusDaemonExit))) { |
| 912 DVLOG(1) << "Failed to launch " << ibus_daemon_command_line; | 985 DVLOG(1) << "Failed to launch " << ibus_daemon_command_line; |
| 913 return false; | |
| 914 } | 986 } |
| 915 return true; | |
| 916 } | 987 } |
| 917 | 988 |
| 918 bool IBusControllerImpl::LaunchProcess(const std::string& command_line, | 989 bool IBusControllerImpl::LaunchProcess(const std::string& command_line, |
| 919 base::ProcessHandle* process_handle, | 990 base::ProcessHandle* process_handle, |
| 920 GChildWatchFunc watch_func) { | 991 GChildWatchFunc watch_func) { |
| 921 std::vector<std::string> argv; | 992 std::vector<std::string> argv; |
| 922 base::ProcessHandle handle = base::kNullProcessHandle; | 993 base::ProcessHandle handle = base::kNullProcessHandle; |
| 923 | 994 |
| 924 base::SplitString(command_line, ' ', &argv); | 995 base::SplitString(command_line, ' ', &argv); |
| 925 | 996 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 978 | 1049 |
| 979 // static | 1050 // static |
| 980 bool IBusControllerImpl::FindAndUpdatePropertyForTesting( | 1051 bool IBusControllerImpl::FindAndUpdatePropertyForTesting( |
| 981 const chromeos::input_method::InputMethodProperty& new_prop, | 1052 const chromeos::input_method::InputMethodProperty& new_prop, |
| 982 chromeos::input_method::InputMethodPropertyList* prop_list) { | 1053 chromeos::input_method::InputMethodPropertyList* prop_list) { |
| 983 return FindAndUpdateProperty(new_prop, prop_list); | 1054 return FindAndUpdateProperty(new_prop, prop_list); |
| 984 } | 1055 } |
| 985 | 1056 |
| 986 } // namespace input_method | 1057 } // namespace input_method |
| 987 } // namespace chromeos | 1058 } // namespace chromeos |
| OLD | NEW |