Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(379)

Side by Side Diff: chrome/browser/chromeos/input_method/ibus_controller_impl.cc

Issue 10159004: Extends DBusThreadManager to connect ibus-bus. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Apply comments. Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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], &current_property_list_); 999 FindAndUpdateProperty(prop_list[i], &current_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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698