| 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 class IBusAddressWatcher { |
| 368 public: |
| 369 class IBusAddressFileWatcherDelegate |
| 370 : public base::files::FilePathWatcher::Delegate { |
| 371 public: |
| 372 IBusAddressFileWatcherDelegate( |
| 373 const std::string& ibus_address, |
| 374 IBusControllerImpl* controller, |
| 375 IBusAddressWatcher* watcher) |
| 376 : ibus_address_(ibus_address), |
| 377 controller_(controller), |
| 378 watcher_(watcher) { |
| 379 DCHECK(watcher); |
| 380 DCHECK(!ibus_address.empty()); |
| 381 } |
| 382 |
| 383 virtual ~IBusAddressFileWatcherDelegate() {} |
| 384 |
| 385 virtual void OnFilePathChanged(const FilePath& file_path) OVERRIDE { |
| 386 if (!watcher_->IsWatching()) |
| 387 return; |
| 388 bool success = content::BrowserThread::PostTask( |
| 389 content::BrowserThread::UI, |
| 390 FROM_HERE, |
| 391 base::Bind( |
| 392 &IBusControllerImpl::IBusDaemonInitializationDone, |
| 393 controller_, |
| 394 ibus_address_)); |
| 395 DCHECK(success); |
| 396 watcher_->StopSoon(); |
| 397 } |
| 398 |
| 399 private: |
| 400 // The ibus-daemon address. |
| 401 const std::string ibus_address_; |
| 402 IBusControllerImpl* controller_; |
| 403 IBusAddressWatcher* watcher_; |
| 404 |
| 405 DISALLOW_COPY_AND_ASSIGN(IBusAddressFileWatcherDelegate); |
| 406 }; |
| 407 |
| 408 static void Start(const std::string& ibus_address, |
| 409 IBusControllerImpl* controller) { |
| 410 IBusAddressWatcher* instance = IBusAddressWatcher::Get(); |
| 411 scoped_ptr<base::Environment> env(base::Environment::Create()); |
| 412 std::string address_file_path; |
| 413 // TODO(nona): move reading environment variables to UI thread. |
| 414 env->GetVar("IBUS_ADDRESS_FILE", &address_file_path); |
| 415 DCHECK(!address_file_path.empty()); |
| 416 |
| 417 if (instance->IsWatching()) |
| 418 instance->StopNow(); |
| 419 instance->watcher_ = new base::files::FilePathWatcher; |
| 420 |
| 421 // The |delegate| is owned by watcher. |
| 422 IBusAddressFileWatcherDelegate* delegate = |
| 423 new IBusAddressFileWatcherDelegate(ibus_address, controller, instance); |
| 424 bool result = instance->watcher_->Watch(FilePath(address_file_path), |
| 425 delegate); |
| 426 DCHECK(result); |
| 427 } |
| 428 |
| 429 void StopNow() { |
| 430 delete watcher_; |
| 431 watcher_ = NULL; |
| 432 } |
| 433 |
| 434 void StopSoon() { |
| 435 if (!watcher_) |
| 436 return; |
| 437 MessageLoop::current()->DeleteSoon(FROM_HERE, watcher_); |
| 438 watcher_ = NULL; |
| 439 } |
| 440 |
| 441 bool IsWatching() const { |
| 442 return watcher_ != NULL; |
| 443 } |
| 444 |
| 445 private: |
| 446 static IBusAddressWatcher* Get() { |
| 447 static IBusAddressWatcher* instance = new IBusAddressWatcher; |
| 448 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
| 449 return instance; |
| 450 } |
| 451 |
| 452 // Singleton |
| 453 IBusAddressWatcher() |
| 454 : watcher_(NULL) {} |
| 455 base::files::FilePathWatcher* watcher_; |
| 456 |
| 457 DISALLOW_COPY_AND_ASSIGN(IBusAddressWatcher); |
| 458 }; |
| 459 |
| 360 } // namespace | 460 } // namespace |
| 361 | 461 |
| 362 IBusControllerImpl::IBusControllerImpl() | 462 IBusControllerImpl::IBusControllerImpl() |
| 363 : ibus_(NULL), | 463 : ibus_(NULL), |
| 364 ibus_config_(NULL), | 464 ibus_config_(NULL), |
| 365 should_launch_daemon_(false), | 465 process_handle_(base::kNullProcessHandle), |
| 366 process_handle_(base::kNullProcessHandle) { | 466 ibus_daemon_status_(IBUS_DAEMON_STOP), |
| 467 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| 367 } | 468 } |
| 368 | 469 |
| 369 IBusControllerImpl::~IBusControllerImpl() { | 470 IBusControllerImpl::~IBusControllerImpl() { |
| 370 // Disconnect signals so the handler functions will not be called with | 471 // Disconnect signals so the handler functions will not be called with |
| 371 // |this| which is already freed. | 472 // |this| which is already freed. |
| 372 if (ibus_) { | 473 if (ibus_) { |
| 373 g_signal_handlers_disconnect_by_func( | 474 g_signal_handlers_disconnect_by_func( |
| 374 ibus_, | 475 ibus_, |
| 375 reinterpret_cast<gpointer>(G_CALLBACK(BusConnectedThunk)), | 476 reinterpret_cast<gpointer>(G_CALLBACK(BusConnectedThunk)), |
| 376 this); | 477 this); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 398 g_signal_handlers_disconnect_by_func( | 499 g_signal_handlers_disconnect_by_func( |
| 399 ibus_panel_service, | 500 ibus_panel_service, |
| 400 reinterpret_cast<gpointer>(G_CALLBACK(UpdatePropertyThunk)), | 501 reinterpret_cast<gpointer>(G_CALLBACK(UpdatePropertyThunk)), |
| 401 this); | 502 this); |
| 402 } | 503 } |
| 403 } | 504 } |
| 404 } | 505 } |
| 405 | 506 |
| 406 bool IBusControllerImpl::Start() { | 507 bool IBusControllerImpl::Start() { |
| 407 MaybeInitializeIBusBus(); | 508 MaybeInitializeIBusBus(); |
| 408 should_launch_daemon_ = true; | |
| 409 if (IBusConnectionsAreAlive()) | 509 if (IBusConnectionsAreAlive()) |
| 410 return true; | 510 return true; |
| 411 return MaybeLaunchIBusDaemon(); | 511 if (ibus_daemon_status_ == IBUS_DAEMON_STOP || |
| 512 ibus_daemon_status_ == IBUS_DAEMON_SHUTTING_DOWN) { |
| 513 return StartIBusDaemon(); |
| 514 } |
| 515 return true; |
| 412 } | 516 } |
| 413 | 517 |
| 414 void IBusControllerImpl::Reset() { | 518 void IBusControllerImpl::Reset() { |
| 415 if (!IBusConnectionsAreAlive()) | 519 if (!IBusConnectionsAreAlive()) |
| 416 return; | 520 return; |
| 417 IBusInputContext* context = | 521 IBusInputContext* context = |
| 418 GetInputContext(current_input_context_path_, ibus_); | 522 GetInputContext(current_input_context_path_, ibus_); |
| 419 if (!context) | 523 if (!context) |
| 420 return; | 524 return; |
| 421 ibus_input_context_reset(context); | 525 ibus_input_context_reset(context); |
| 422 } | 526 } |
| 423 | 527 |
| 424 bool IBusControllerImpl::Stop() { | 528 bool IBusControllerImpl::Stop() { |
| 529 if (ibus_daemon_status_ == IBUS_DAEMON_SHUTTING_DOWN || |
| 530 ibus_daemon_status_ == IBUS_DAEMON_STOP) { |
| 531 return true; |
| 532 } |
| 533 |
| 534 ibus_daemon_status_ = IBUS_DAEMON_SHUTTING_DOWN; |
| 535 // TODO(nona): Shutdown ibus-bus connection. |
| 425 if (IBusConnectionsAreAlive()) { | 536 if (IBusConnectionsAreAlive()) { |
| 426 // Ask IBus to exit *asynchronously*. | 537 // Ask IBus to exit *asynchronously*. |
| 427 ibus_bus_exit_async(ibus_, | 538 ibus_bus_exit_async(ibus_, |
| 428 FALSE /* do not restart */, | 539 FALSE /* do not restart */, |
| 429 -1 /* timeout */, | 540 -1 /* timeout */, |
| 430 NULL /* cancellable */, | 541 NULL /* cancellable */, |
| 431 NULL /* callback */, | 542 NULL /* callback */, |
| 432 NULL /* user_data */); | 543 NULL /* user_data */); |
| 433 if (ibus_config_) { | 544 if (ibus_config_) { |
| 434 // Release |ibus_config_| unconditionally to make sure next | 545 // Release |ibus_config_| unconditionally to make sure next |
| 435 // IBusConnectionsAreAlive() call will return false. | 546 // IBusConnectionsAreAlive() call will return false. |
| 436 g_object_unref(ibus_config_); | 547 g_object_unref(ibus_config_); |
| 437 ibus_config_ = NULL; | 548 ibus_config_ = NULL; |
| 438 } | 549 } |
| 439 } else if (process_handle_ != base::kNullProcessHandle) { | 550 } else { |
| 440 base::KillProcess(process_handle_, -1, false /* wait */); | 551 base::KillProcess(process_handle_, -1, false /* wait */); |
| 441 DVLOG(1) << "Killing ibus-daemon. PID=" | 552 DVLOG(1) << "Killing ibus-daemon. PID=" |
| 442 << base::GetProcId(process_handle_); | 553 << base::GetProcId(process_handle_); |
| 443 } else { | |
| 444 // The daemon hasn't been started yet. | |
| 445 } | 554 } |
| 446 | |
| 447 process_handle_ = base::kNullProcessHandle; | 555 process_handle_ = base::kNullProcessHandle; |
| 448 should_launch_daemon_ = false; | |
| 449 return true; | 556 return true; |
| 450 } | 557 } |
| 451 | 558 |
| 452 bool IBusControllerImpl::ChangeInputMethod(const std::string& id) { | 559 bool IBusControllerImpl::ChangeInputMethod(const std::string& id) { |
| 453 DCHECK(should_launch_daemon_); | 560 if (ibus_daemon_status_ == IBUS_DAEMON_SHUTTING_DOWN || |
| 561 ibus_daemon_status_ == IBUS_DAEMON_STOP) { |
| 562 return false; |
| 563 } |
| 454 | 564 |
| 455 // Sanity checks. | 565 // Sanity checks. |
| 456 DCHECK(!InputMethodUtil::IsKeyboardLayout(id)); | 566 DCHECK(!InputMethodUtil::IsKeyboardLayout(id)); |
| 457 if (!whitelist_.InputMethodIdIsWhitelisted(id) && | 567 if (!whitelist_.InputMethodIdIsWhitelisted(id) && |
| 458 !InputMethodUtil::IsExtensionInputMethod(id)) | 568 !InputMethodUtil::IsExtensionInputMethod(id)) |
| 459 return false; | 569 return false; |
| 460 | 570 |
| 461 // Clear input method properties unconditionally if |id| is not equal to | 571 // Clear input method properties unconditionally if |id| is not equal to |
| 462 // |current_input_method_id_|. | 572 // |current_input_method_id_|. |
| 463 // | 573 // |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 IBusInputContext* context = | 675 IBusInputContext* context = |
| 566 GetInputContext(current_input_context_path_, ibus_); | 676 GetInputContext(current_input_context_path_, ibus_); |
| 567 if (!context) | 677 if (!context) |
| 568 return; | 678 return; |
| 569 ibus_input_context_cancel_hand_writing(context, n_strokes); | 679 ibus_input_context_cancel_hand_writing(context, n_strokes); |
| 570 g_object_unref(context); | 680 g_object_unref(context); |
| 571 } | 681 } |
| 572 #endif | 682 #endif |
| 573 | 683 |
| 574 bool IBusControllerImpl::IBusConnectionsAreAlive() { | 684 bool IBusControllerImpl::IBusConnectionsAreAlive() { |
| 575 return (process_handle_ != base::kNullProcessHandle) && | 685 return (ibus_daemon_status_ == IBUS_DAEMON_RUNNING) && |
| 576 ibus_ && ibus_bus_is_connected(ibus_) && ibus_config_; | 686 ibus_ && ibus_bus_is_connected(ibus_) && ibus_config_; |
| 577 } | 687 } |
| 578 | 688 |
| 579 void IBusControllerImpl::MaybeRestoreConnections() { | 689 void IBusControllerImpl::MaybeRestoreConnections() { |
| 580 if (IBusConnectionsAreAlive()) | 690 if (IBusConnectionsAreAlive()) |
| 581 return; | 691 return; |
| 582 MaybeRestoreIBusConfig(); | 692 MaybeRestoreIBusConfig(); |
| 583 if (IBusConnectionsAreAlive()) { | 693 if (IBusConnectionsAreAlive()) { |
| 584 DVLOG(1) << "ibus-daemon and ibus-memconf processes are ready."; | 694 DVLOG(1) << "ibus-daemon and ibus-memconf processes are ready."; |
| 585 ConnectPanelServiceSignals(); | 695 ConnectPanelServiceSignals(); |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 885 | 995 |
| 886 // Notify the change. | 996 // Notify the change. |
| 887 if (!prop_list.empty()) { | 997 if (!prop_list.empty()) { |
| 888 for (size_t i = 0; i < prop_list.size(); ++i) { | 998 for (size_t i = 0; i < prop_list.size(); ++i) { |
| 889 FindAndUpdateProperty(prop_list[i], ¤t_property_list_); | 999 FindAndUpdateProperty(prop_list[i], ¤t_property_list_); |
| 890 } | 1000 } |
| 891 FOR_EACH_OBSERVER(Observer, observers_, PropertyChanged()); | 1001 FOR_EACH_OBSERVER(Observer, observers_, PropertyChanged()); |
| 892 } | 1002 } |
| 893 } | 1003 } |
| 894 | 1004 |
| 895 bool IBusControllerImpl::MaybeLaunchIBusDaemon() { | 1005 bool IBusControllerImpl::StartIBusDaemon() { |
| 896 static const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon"; | 1006 if (ibus_daemon_status_ == IBUS_DAEMON_INITIALIZING || |
| 897 | 1007 ibus_daemon_status_ == IBUS_DAEMON_RUNNING) { |
| 898 if (process_handle_ != base::kNullProcessHandle) { | |
| 899 DVLOG(1) << "MaybeLaunchIBusDaemon: ibus-daemon is already running."; | 1008 DVLOG(1) << "MaybeLaunchIBusDaemon: ibus-daemon is already running."; |
| 900 return false; | 1009 return false; |
| 901 } | 1010 } |
| 902 if (!should_launch_daemon_) | |
| 903 return false; | |
| 904 | 1011 |
| 1012 ibus_daemon_status_ = IBUS_DAEMON_INITIALIZING; |
| 1013 ibus_daemon_address_ = base::StringPrintf( |
| 1014 "unix:abstract=ibus-%d", |
| 1015 base::RandInt(0, std::numeric_limits<int>::max())); |
| 1016 |
| 1017 // Set up ibus-daemon address file watcher before launching ibus-daemon, |
| 1018 // because if watcher starts after ibus-daemon, we may miss the ibus |
| 1019 // connection initialization. |
| 1020 bool success = content::BrowserThread::PostTaskAndReply( |
| 1021 content::BrowserThread::FILE, |
| 1022 FROM_HERE, |
| 1023 base::Bind(&IBusAddressWatcher::Start, |
| 1024 ibus_daemon_address_, |
| 1025 base::Unretained(this)), |
| 1026 base::Bind(&IBusControllerImpl::LaunchIBusDaemon, |
| 1027 weak_ptr_factory_.GetWeakPtr(), |
| 1028 ibus_daemon_address_)); |
| 1029 DCHECK(success); |
| 1030 return true; |
| 1031 } |
| 1032 |
| 1033 void IBusControllerImpl::LaunchIBusDaemon(const std::string& ibus_address) { |
| 1034 DCHECK_EQ(base::kNullProcessHandle, process_handle_); |
| 1035 static const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon"; |
| 905 // TODO(zork): Send output to /var/log/ibus.log | 1036 // TODO(zork): Send output to /var/log/ibus.log |
| 906 const std::string ibus_daemon_command_line = | 1037 const std::string ibus_daemon_command_line = |
| 907 base::StringPrintf("%s --panel=disable --cache=none --restart --replace", | 1038 base::StringPrintf("%s --panel=disable --cache=none --restart --replace" |
| 908 kIBusDaemonPath); | 1039 " --address=%s", |
| 1040 kIBusDaemonPath, |
| 1041 ibus_address.c_str()); |
| 909 if (!LaunchProcess(ibus_daemon_command_line, | 1042 if (!LaunchProcess(ibus_daemon_command_line, |
| 910 &process_handle_, | 1043 &process_handle_, |
| 911 reinterpret_cast<GChildWatchFunc>(OnIBusDaemonExit))) { | 1044 reinterpret_cast<GChildWatchFunc>(OnIBusDaemonExit))) { |
| 912 DVLOG(1) << "Failed to launch " << ibus_daemon_command_line; | 1045 DVLOG(1) << "Failed to launch " << ibus_daemon_command_line; |
| 913 return false; | |
| 914 } | 1046 } |
| 915 return true; | |
| 916 } | 1047 } |
| 917 | 1048 |
| 918 bool IBusControllerImpl::LaunchProcess(const std::string& command_line, | 1049 bool IBusControllerImpl::LaunchProcess(const std::string& command_line, |
| 919 base::ProcessHandle* process_handle, | 1050 base::ProcessHandle* process_handle, |
| 920 GChildWatchFunc watch_func) { | 1051 GChildWatchFunc watch_func) { |
| 921 std::vector<std::string> argv; | 1052 std::vector<std::string> argv; |
| 922 base::ProcessHandle handle = base::kNullProcessHandle; | 1053 base::ProcessHandle handle = base::kNullProcessHandle; |
| 923 | 1054 |
| 924 base::SplitString(command_line, ' ', &argv); | 1055 base::SplitString(command_line, ' ', &argv); |
| 925 | 1056 |
| 926 if (!base::LaunchProcess(argv, base::LaunchOptions(), &handle)) { | 1057 if (!base::LaunchProcess(argv, base::LaunchOptions(), &handle)) { |
| 927 DVLOG(1) << "Could not launch: " << command_line; | 1058 DVLOG(1) << "Could not launch: " << command_line; |
| 928 return false; | 1059 return false; |
| 929 } | 1060 } |
| 930 | 1061 |
| 931 // g_child_watch_add is necessary to prevent the process from becoming a | 1062 // g_child_watch_add is necessary to prevent the process from becoming a |
| 932 // zombie. | 1063 // zombie. |
| 933 // TODO(yusukes): port g_child_watch_add to base/process_utils_posix.cc. | 1064 // TODO(yusukes): port g_child_watch_add to base/process_utils_posix.cc. |
| 934 const base::ProcessId pid = base::GetProcId(handle); | 1065 const base::ProcessId pid = base::GetProcId(handle); |
| 935 g_child_watch_add(pid, watch_func, this); | 1066 g_child_watch_add(pid, watch_func, this); |
| 936 | 1067 |
| 937 *process_handle = handle; | 1068 *process_handle = handle; |
| 938 DVLOG(1) << command_line << "is started. PID=" << pid; | 1069 DVLOG(1) << command_line << "is started. PID=" << pid; |
| 939 return true; | 1070 return true; |
| 940 } | 1071 } |
| 941 | 1072 |
| 942 // static | 1073 // static |
| 1074 void IBusControllerImpl::IBusDaemonInitializationDone( |
| 1075 IBusControllerImpl* controller, |
| 1076 const std::string& ibus_address) { |
| 1077 if (controller->ibus_daemon_address_ != ibus_address) |
| 1078 return; |
| 1079 |
| 1080 if (controller->ibus_daemon_status_ != IBUS_DAEMON_INITIALIZING) { |
| 1081 // Stop() or OnIBusDaemonExit() has already been called. |
| 1082 return; |
| 1083 } |
| 1084 chromeos::DBusThreadManager::Get()->InitIBusBus(ibus_address); |
| 1085 controller->ibus_daemon_status_ = IBUS_DAEMON_RUNNING; |
| 1086 VLOG(1) << "The ibus-daemon initialization is done."; |
| 1087 } |
| 1088 |
| 1089 // static |
| 943 void IBusControllerImpl::SetInputMethodConfigCallback(GObject* source_object, | 1090 void IBusControllerImpl::SetInputMethodConfigCallback(GObject* source_object, |
| 944 GAsyncResult* res, | 1091 GAsyncResult* res, |
| 945 gpointer user_data) { | 1092 gpointer user_data) { |
| 946 IBusConfig* config = IBUS_CONFIG(user_data); | 1093 IBusConfig* config = IBUS_CONFIG(user_data); |
| 947 g_return_if_fail(config); | 1094 g_return_if_fail(config); |
| 948 | 1095 |
| 949 GError* error = NULL; | 1096 GError* error = NULL; |
| 950 const gboolean result = | 1097 const gboolean result = |
| 951 ibus_config_set_value_async_finish(config, res, &error); | 1098 ibus_config_set_value_async_finish(config, res, &error); |
| 952 | 1099 |
| 953 if (!result) { | 1100 if (!result) { |
| 954 std::string message = "(unknown error)"; | 1101 std::string message = "(unknown error)"; |
| 955 if (error && error->message) { | 1102 if (error && error->message) { |
| 956 message = error->message; | 1103 message = error->message; |
| 957 } | 1104 } |
| 958 DVLOG(1) << "ibus_config_set_value_async failed: " << message; | 1105 DVLOG(1) << "ibus_config_set_value_async failed: " << message; |
| 959 } | 1106 } |
| 960 | 1107 |
| 961 if (error) | 1108 if (error) |
| 962 g_error_free(error); | 1109 g_error_free(error); |
| 963 g_object_unref(config); | 1110 g_object_unref(config); |
| 964 } | 1111 } |
| 965 | 1112 |
| 966 // static | 1113 // static |
| 967 void IBusControllerImpl::OnIBusDaemonExit(GPid pid, | 1114 void IBusControllerImpl::OnIBusDaemonExit(GPid pid, |
| 968 gint status, | 1115 gint status, |
| 969 IBusControllerImpl* controller) { | 1116 IBusControllerImpl* controller) { |
| 970 if (controller->process_handle_ != base::kNullProcessHandle && | 1117 if (controller->process_handle_ != base::kNullProcessHandle) { |
| 971 base::GetProcId(controller->process_handle_) == pid) { | 1118 if (base::GetProcId(controller->process_handle_) == pid) { |
| 972 controller->process_handle_ = base::kNullProcessHandle; | 1119 // ibus-daemon crashed. |
| 1120 // TODO(nona): Shutdown ibus-bus connection. |
| 1121 controller->process_handle_ = base::kNullProcessHandle; |
| 1122 } else { |
| 1123 // This condition is as follows. |
| 1124 // 1. Called Stop (process_handle_ becomes null) |
| 1125 // 2. Called LaunchProcess (process_handle_ becomes new instance) |
| 1126 // 3. Callbacked OnIBusDaemonExit for old instance and reach here. |
| 1127 // In this case, we should not reset process_handle_ as null, and do not |
| 1128 // re-launch ibus-daemon. |
| 1129 return; |
| 1130 } |
| 973 } | 1131 } |
| 974 // Restart the daemon if needed. | 1132 |
| 975 controller->MaybeLaunchIBusDaemon(); | 1133 const IBusDaemonStatus on_exit_state = controller->ibus_daemon_status_; |
| 1134 controller->ibus_daemon_status_ = IBUS_DAEMON_STOP; |
| 1135 if (on_exit_state == IBUS_DAEMON_SHUTTING_DOWN) { |
| 1136 // Normal exitting, so do nothing. |
| 1137 return; |
| 1138 } |
| 1139 |
| 1140 LOG(ERROR) << "The ibus-daemon crashed. Re-launching..."; |
| 1141 controller->StartIBusDaemon(); |
| 976 } | 1142 } |
| 977 #endif // defined(HAVE_IBUS) | 1143 #endif // defined(HAVE_IBUS) |
| 978 | 1144 |
| 979 // static | 1145 // static |
| 980 bool IBusControllerImpl::FindAndUpdatePropertyForTesting( | 1146 bool IBusControllerImpl::FindAndUpdatePropertyForTesting( |
| 981 const chromeos::input_method::InputMethodProperty& new_prop, | 1147 const chromeos::input_method::InputMethodProperty& new_prop, |
| 982 chromeos::input_method::InputMethodPropertyList* prop_list) { | 1148 chromeos::input_method::InputMethodPropertyList* prop_list) { |
| 983 return FindAndUpdateProperty(new_prop, prop_list); | 1149 return FindAndUpdateProperty(new_prop, prop_list); |
| 984 } | 1150 } |
| 985 | 1151 |
| 986 } // namespace input_method | 1152 } // namespace input_method |
| 987 } // namespace chromeos | 1153 } // namespace chromeos |
| OLD | NEW |