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

Side by Side Diff: chrome/browser/chromeos/cros/input_method_library.cc

Issue 6714044: Remove g_spawn_async. Use base/process_utils.h instead. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/cros/input_method_library.h" 5 #include "chrome/browser/chromeos/cros/input_method_library.h"
6 6
7 #include <glib.h> 7 #include <glib.h>
8 #include <signal.h>
9 8
10 #include "unicode/uloc.h" 9 #include "unicode/uloc.h"
11 10
12 #include "base/basictypes.h" 11 #include "base/basictypes.h"
13 #include "base/message_loop.h" 12 #include "base/message_loop.h"
13 #include "base/process_util.h"
14 #include "base/string_split.h"
14 #include "base/string_util.h" 15 #include "base/string_util.h"
15 #include "chrome/browser/browser_process.h" 16 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/chromeos/cros/cros_library.h" 17 #include "chrome/browser/chromeos/cros/cros_library.h"
17 #include "chrome/browser/chromeos/cros/keyboard_library.h" 18 #include "chrome/browser/chromeos/cros/keyboard_library.h"
18 #include "chrome/browser/chromeos/input_method/candidate_window.h" 19 #include "chrome/browser/chromeos/input_method/candidate_window.h"
19 #include "chrome/browser/chromeos/input_method/input_method_util.h" 20 #include "chrome/browser/chromeos/input_method/input_method_util.h"
20 #include "chrome/browser/chromeos/language_preferences.h" 21 #include "chrome/browser/chromeos/language_preferences.h"
21 #include "content/browser/browser_thread.h" 22 #include "content/browser/browser_thread.h"
22 #include "content/common/notification_observer.h" 23 #include "content/common/notification_observer.h"
23 #include "content/common/notification_registrar.h" 24 #include "content/common/notification_registrar.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 public: 56 public:
56 InputMethodLibraryImpl() 57 InputMethodLibraryImpl()
57 : input_method_status_connection_(NULL), 58 : input_method_status_connection_(NULL),
58 previous_input_method_("", "", "", ""), 59 previous_input_method_("", "", "", ""),
59 current_input_method_("", "", "", ""), 60 current_input_method_("", "", "", ""),
60 should_launch_ime_(false), 61 should_launch_ime_(false),
61 ime_connected_(false), 62 ime_connected_(false),
62 defer_ime_startup_(false), 63 defer_ime_startup_(false),
63 enable_auto_ime_shutdown_(true), 64 enable_auto_ime_shutdown_(true),
64 should_change_input_method_(false), 65 should_change_input_method_(false),
65 ibus_daemon_process_id_(0), 66 ibus_daemon_process_handle_(base::kNullProcessHandle),
66 initialized_successfully_(false), 67 initialized_successfully_(false),
67 candidate_window_controller_(NULL) { 68 candidate_window_controller_(NULL) {
68 // Here, we use the fallback input method descriptor but 69 // Here, we use the fallback input method descriptor but
69 // |current_input_method_| will be updated as soon as the login screen 70 // |current_input_method_| will be updated as soon as the login screen
70 // is shown or the user is logged in, so there is no problem. 71 // is shown or the user is logged in, so there is no problem.
71 current_input_method_ = input_method::GetFallbackInputMethodDescriptor(); 72 current_input_method_ = input_method::GetFallbackInputMethodDescriptor();
72 active_input_method_ids_.push_back(current_input_method_.id); 73 active_input_method_ids_.push_back(current_input_method_.id);
73 // Observe APP_TERMINATING to stop input method daemon gracefully. 74 // Observe APP_TERMINATING to stop input method daemon gracefully.
74 // We should not use APP_EXITING here since logout might be canceled by 75 // We should not use APP_EXITING here since logout might be canceled by
75 // JavaScript after APP_EXITING is sent (crosbug.com/11055). 76 // JavaScript after APP_EXITING is sent (crosbug.com/11055).
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 return chromeos::GetSupportedInputMethodDescriptors(); 164 return chromeos::GetSupportedInputMethodDescriptors();
164 } 165 }
165 166
166 virtual void ChangeInputMethod(const std::string& input_method_id) { 167 virtual void ChangeInputMethod(const std::string& input_method_id) {
167 // Changing the input method isn't guaranteed to succeed here, but we 168 // Changing the input method isn't guaranteed to succeed here, but we
168 // should remember the last one regardless. See comments in 169 // should remember the last one regardless. See comments in
169 // FlushImeConfig() for details. 170 // FlushImeConfig() for details.
170 tentative_current_input_method_id_ = input_method_id; 171 tentative_current_input_method_id_ = input_method_id;
171 // If the input method daemon is not running and the specified input 172 // If the input method daemon is not running and the specified input
172 // method is a keyboard layout, switch the keyboard directly. 173 // method is a keyboard layout, switch the keyboard directly.
173 if (ibus_daemon_process_id_ == 0 && 174 if (ibus_daemon_process_handle_ == base::kNullProcessHandle &&
174 chromeos::input_method::IsKeyboardLayout(input_method_id)) { 175 chromeos::input_method::IsKeyboardLayout(input_method_id)) {
175 // We shouldn't use SetCurrentKeyboardLayoutByName() here. See 176 // We shouldn't use SetCurrentKeyboardLayoutByName() here. See
176 // comments at ChangeCurrentInputMethod() for details. 177 // comments at ChangeCurrentInputMethod() for details.
177 ChangeCurrentInputMethodFromId(input_method_id); 178 ChangeCurrentInputMethodFromId(input_method_id);
178 } else { 179 } else {
179 // Otherwise, start the input method daemon, and change the input 180 // Otherwise, start the input method daemon, and change the input
180 // method via the damon. 181 // method via the damon.
181 StartInputMethodDaemon(); 182 StartInputMethodDaemon();
182 // ChangeInputMethodViaIBus() fails if the IBus daemon is not 183 // ChangeInputMethodViaIBus() fails if the IBus daemon is not
183 // ready yet. In this case, we'll defer the input method change 184 // ready yet. In this case, we'll defer the input method change
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 } 591 }
591 592
592 // Updates the properties used by the current input method. 593 // Updates the properties used by the current input method.
593 void UpdateProperty(const ImePropertyList& prop_list) { 594 void UpdateProperty(const ImePropertyList& prop_list) {
594 for (size_t i = 0; i < prop_list.size(); ++i) { 595 for (size_t i = 0; i < prop_list.size(); ++i) {
595 FindAndUpdateProperty(prop_list[i], &current_ime_properties_); 596 FindAndUpdateProperty(prop_list[i], &current_ime_properties_);
596 } 597 }
597 } 598 }
598 599
599 // Launches an input method procsess specified by the given command 600 // Launches an input method procsess specified by the given command
600 // line. On success, returns true and stores the process ID in 601 // line. On success, returns true and stores the process handle in
601 // |process_id|. Otherwise, returns false, and the contents of 602 // |process_handle|. Otherwise, returns false, and the contents of
602 // |process_id| is untouched. OnImeShutdown will be called when the 603 // |process_handle| is untouched. OnImeShutdown will be called when the
603 // process terminates. 604 // process terminates.
604 bool LaunchInputMethodProcess(const std::string& command_line, 605 bool LaunchInputMethodProcess(const std::string& command_line,
605 int* process_id) { 606 base::ProcessHandle* process_handle) {
606 GError *error = NULL; 607 std::vector<std::string> argv;
607 gchar **argv = NULL; 608 base::file_handle_mapping_vector fds_to_remap;
608 gint argc = NULL; 609 base::ProcessHandle handle = base::kNullProcessHandle;
610
609 // TODO(zork): export "LD_PRELOAD=/usr/lib/libcrash.so" 611 // TODO(zork): export "LD_PRELOAD=/usr/lib/libcrash.so"
610 if (!g_shell_parse_argv(command_line.c_str(), &argc, &argv, &error)) { 612 base::SplitString(command_line, ' ', &argv);
611 LOG(ERROR) << "Could not parse command: " << error->message; 613 const bool result = base::LaunchApp(argv,
612 g_error_free(error); 614 fds_to_remap, // no remapping
615 false, // wait
616 &handle);
617 if (!result) {
618 LOG(ERROR) << "Could not launch: " << command_line;
613 return false; 619 return false;
614 } 620 }
615 621 g_child_watch_add(base::GetProcId(handle),
Zachary Kuznia 2011/03/21 10:43:52 Perhaps we should add a version of this function t
satorux1 2011/03/21 11:52:11 I agree. Let's add a TODO here.
Yusuke Sato 2011/03/21 12:08:17 Sure, added TODO. On 2011/03/21 10:43:52, Zachary
Yusuke Sato 2011/03/21 12:08:17 Done.
616 int pid = 0; 622 reinterpret_cast<GChildWatchFunc>(OnImeShutdown),
617 const GSpawnFlags kFlags = G_SPAWN_DO_NOT_REAP_CHILD;
618 const gboolean result = g_spawn_async(NULL, argv, NULL,
619 kFlags, NULL, NULL,
620 &pid, &error);
621 g_strfreev(argv);
622 if (!result) {
623 LOG(ERROR) << "Could not launch: " << command_line << ": "
624 << error->message;
625 g_error_free(error);
626 return false;
627 }
628 g_child_watch_add(pid, reinterpret_cast<GChildWatchFunc>(OnImeShutdown),
629 this); 623 this);
630 624
631 *process_id = pid; 625 *process_handle = handle;
632 VLOG(1) << command_line << " (PID=" << pid << ") is started"; 626 VLOG(1) << command_line << " (PID=" << base::GetProcId(handle)
627 << ") is started";
633 return true; 628 return true;
634 } 629 }
635 630
636 // Launches input method daemon if these are not yet running. 631 // Launches input method daemon if these are not yet running.
637 void MaybeLaunchInputMethodDaemon() { 632 void MaybeLaunchInputMethodDaemon() {
638 // CandidateWindowController requires libcros to be loaded. Besides, 633 // CandidateWindowController requires libcros to be loaded. Besides,
639 // launching ibus-daemon without libcros loaded doesn't make sense. 634 // launching ibus-daemon without libcros loaded doesn't make sense.
640 if (!initialized_successfully_) 635 if (!initialized_successfully_)
641 return; 636 return;
642 637
643 if (!should_launch_ime_) { 638 if (!should_launch_ime_) {
644 return; 639 return;
645 } 640 }
646 641
647 if (!candidate_window_controller_.get()) { 642 if (!candidate_window_controller_.get()) {
648 candidate_window_controller_.reset(new CandidateWindowController); 643 candidate_window_controller_.reset(new CandidateWindowController);
649 if (!candidate_window_controller_->Init()) { 644 if (!candidate_window_controller_->Init()) {
650 LOG(WARNING) << "Failed to initialize the candidate window controller"; 645 LOG(WARNING) << "Failed to initialize the candidate window controller";
651 } 646 }
652 } 647 }
653 648
654 if (ibus_daemon_process_id_ == 0) { 649 if (ibus_daemon_process_handle_ == base::kNullProcessHandle) {
655 // TODO(zork): Send output to /var/log/ibus.log 650 // TODO(zork): Send output to /var/log/ibus.log
656 const std::string ibus_daemon_command_line = 651 const std::string ibus_daemon_command_line =
657 StringPrintf("%s --panel=disable --cache=none --restart --replace", 652 StringPrintf("%s --panel=disable --cache=none --restart --replace",
658 kIBusDaemonPath); 653 kIBusDaemonPath);
659 if (!LaunchInputMethodProcess( 654 if (!LaunchInputMethodProcess(
660 ibus_daemon_command_line, &ibus_daemon_process_id_)) { 655 ibus_daemon_command_line, &ibus_daemon_process_handle_)) {
661 LOG(ERROR) << "Failed to launch " << ibus_daemon_command_line; 656 LOG(ERROR) << "Failed to launch " << ibus_daemon_command_line;
662 } 657 }
663 } 658 }
664 } 659 }
665 660
666 // Called when the input method process is shut down. 661 // Called when the input method process is shut down.
667 static void OnImeShutdown(int pid, 662 static void OnImeShutdown(int pid,
668 int status, 663 int status,
669 InputMethodLibraryImpl* library) { 664 InputMethodLibraryImpl* library) {
670 g_spawn_close_pid(pid); 665 if (base::GetProcId(library->ibus_daemon_process_handle_) == pid) {
Zachary Kuznia 2011/03/21 10:43:52 Should we check that we have a handle before calli
Yusuke Sato 2011/03/21 12:08:17 Added the check. (right now, calling GetProcId(kNu
671 if (library->ibus_daemon_process_id_ == pid) { 666 base::CloseProcessHandle(library->ibus_daemon_process_handle_);
672 library->ibus_daemon_process_id_ = 0; 667 library->ibus_daemon_process_handle_ = base::kNullProcessHandle;
673 } 668 }
674 669
675 // Restart input method daemon if needed. 670 // Restart input method daemon if needed.
676 library->MaybeLaunchInputMethodDaemon(); 671 library->MaybeLaunchInputMethodDaemon();
677 } 672 }
678 673
679 // Stops the backend input method daemon. This function should also be 674 // Stops the backend input method daemon. This function should also be
680 // called from MaybeStopInputMethodDaemon(), except one case where we 675 // called from MaybeStopInputMethodDaemon(), except one case where we
681 // stop the input method daemon at Chrome shutdown in Observe(). 676 // stop the input method daemon at Chrome shutdown in Observe().
682 void StopInputMethodDaemon() { 677 void StopInputMethodDaemon() {
683 if (!initialized_successfully_) 678 if (!initialized_successfully_)
684 return; 679 return;
685 680
686 should_launch_ime_ = false; 681 should_launch_ime_ = false;
687 if (ibus_daemon_process_id_) { 682 if (ibus_daemon_process_handle_ != base::kNullProcessHandle) {
688 if (!chromeos::StopInputMethodProcess(input_method_status_connection_)) { 683 if (!chromeos::StopInputMethodProcess(input_method_status_connection_)) {
689 LOG(ERROR) << "StopInputMethodProcess IPC failed. Sending SIGTERM to " 684 LOG(ERROR) << "StopInputMethodProcess IPC failed. Sending SIGTERM to "
690 << "PID " << ibus_daemon_process_id_; 685 << "PID " << base::GetProcId(ibus_daemon_process_handle_);
691 kill(ibus_daemon_process_id_, SIGTERM); 686 base::KillProcess(ibus_daemon_process_handle_, -1, false /* wait */);
692 } 687 }
693 VLOG(1) << "ibus-daemon (PID=" << ibus_daemon_process_id_ << ") is " 688 VLOG(1) << "ibus-daemon (PID="
694 << "terminated"; 689 << base::GetProcId(ibus_daemon_process_handle_)
695 ibus_daemon_process_id_ = 0; 690 << ") is terminated";
691 base::CloseProcessHandle(ibus_daemon_process_handle_);
Zachary Kuznia 2011/03/21 10:43:52 Shouldn't this already be called in OnImeShutdown,
Yusuke Sato 2011/03/21 12:08:17 Let me remove all CloseProcessHandle calls since b
692 ibus_daemon_process_handle_ = base::kNullProcessHandle;
696 } 693 }
697 } 694 }
698 695
699 void SetDeferImeStartup(bool defer) { 696 void SetDeferImeStartup(bool defer) {
700 VLOG(1) << "Setting DeferImeStartup to " << defer; 697 VLOG(1) << "Setting DeferImeStartup to " << defer;
701 defer_ime_startup_ = defer; 698 defer_ime_startup_ = defer;
702 } 699 }
703 700
704 void SetEnableAutoImeShutdown(bool enable) { 701 void SetEnableAutoImeShutdown(bool enable) {
705 enable_auto_ime_shutdown_ = enable; 702 enable_auto_ime_shutdown_ = enable;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
758 bool enable_auto_ime_shutdown_; 755 bool enable_auto_ime_shutdown_;
759 // The ID of the tentative current input method (ex. "mozc"). This value 756 // The ID of the tentative current input method (ex. "mozc"). This value
760 // can be different from the actual current input method, if 757 // can be different from the actual current input method, if
761 // ChangeInputMethod() fails. 758 // ChangeInputMethod() fails.
762 std::string tentative_current_input_method_id_; 759 std::string tentative_current_input_method_id_;
763 // True if we should change the current input method to 760 // True if we should change the current input method to
764 // |tentative_current_input_method_id_| once the queue of the pending config 761 // |tentative_current_input_method_id_| once the queue of the pending config
765 // requests becomes empty. 762 // requests becomes empty.
766 bool should_change_input_method_; 763 bool should_change_input_method_;
767 764
768 // The process id of the IBus daemon. 0 if it's not running. The process 765 // The process handle of the IBus daemon. kNullProcessHandle if it's not
769 // ID 0 is not used in Linux, hence it's safe to use 0 for this purpose. 766 // running.
770 int ibus_daemon_process_id_; 767 base::ProcessHandle ibus_daemon_process_handle_;
771 768
772 // True if initialization is successfully done, meaning that libcros is 769 // True if initialization is successfully done, meaning that libcros is
773 // loaded and input method status monitoring is started. This value 770 // loaded and input method status monitoring is started. This value
774 // should be checked where we call libcros functions. 771 // should be checked where we call libcros functions.
775 bool initialized_successfully_; 772 bool initialized_successfully_;
776 773
777 // The candidate window. This will be deleted when the APP_TERMINATING 774 // The candidate window. This will be deleted when the APP_TERMINATING
778 // message is sent. 775 // message is sent.
779 scoped_ptr<CandidateWindowController> candidate_window_controller_; 776 scoped_ptr<CandidateWindowController> candidate_window_controller_;
780 777
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
1100 } 1097 }
1101 return impl; 1098 return impl;
1102 } 1099 }
1103 } 1100 }
1104 1101
1105 } // namespace chromeos 1102 } // namespace chromeos
1106 1103
1107 // Allows InvokeLater without adding refcounting. This class is a Singleton and 1104 // Allows InvokeLater without adding refcounting. This class is a Singleton and
1108 // won't be deleted until it's last InvokeLater is run. 1105 // won't be deleted until it's last InvokeLater is run.
1109 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::InputMethodLibraryImpl); 1106 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::InputMethodLibraryImpl);
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698