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

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: review fixes 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
616 int pid = 0; 622 // g_child_watch_add is necessary to prevent the process from becoming a
617 const GSpawnFlags kFlags = G_SPAWN_DO_NOT_REAP_CHILD; 623 // zombie.
618 const gboolean result = g_spawn_async(NULL, argv, NULL, 624 // TODO(yusukes): port g_child_watch_add to base/process_utils_posix.cc.
619 kFlags, NULL, NULL, 625 const base::ProcessId pid = base::GetProcId(handle);
620 &pid, &error); 626 g_child_watch_add(pid,
621 g_strfreev(argv); 627 reinterpret_cast<GChildWatchFunc>(OnImeShutdown),
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); 628 this);
630 629
631 *process_id = pid; 630 *process_handle = handle;
632 VLOG(1) << command_line << " (PID=" << pid << ") is started"; 631 VLOG(1) << command_line << " (PID=" << pid << ") is started";
633 return true; 632 return true;
634 } 633 }
635 634
636 // Launches input method daemon if these are not yet running. 635 // Launches input method daemon if these are not yet running.
637 void MaybeLaunchInputMethodDaemon() { 636 void MaybeLaunchInputMethodDaemon() {
638 // CandidateWindowController requires libcros to be loaded. Besides, 637 // CandidateWindowController requires libcros to be loaded. Besides,
639 // launching ibus-daemon without libcros loaded doesn't make sense. 638 // launching ibus-daemon without libcros loaded doesn't make sense.
640 if (!initialized_successfully_) 639 if (!initialized_successfully_)
641 return; 640 return;
642 641
643 if (!should_launch_ime_) { 642 if (!should_launch_ime_) {
644 return; 643 return;
645 } 644 }
646 645
647 if (!candidate_window_controller_.get()) { 646 if (!candidate_window_controller_.get()) {
648 candidate_window_controller_.reset(new CandidateWindowController); 647 candidate_window_controller_.reset(new CandidateWindowController);
649 if (!candidate_window_controller_->Init()) { 648 if (!candidate_window_controller_->Init()) {
650 LOG(WARNING) << "Failed to initialize the candidate window controller"; 649 LOG(WARNING) << "Failed to initialize the candidate window controller";
651 } 650 }
652 } 651 }
653 652
654 if (ibus_daemon_process_id_ == 0) { 653 if (ibus_daemon_process_handle_ == base::kNullProcessHandle) {
655 // TODO(zork): Send output to /var/log/ibus.log 654 // TODO(zork): Send output to /var/log/ibus.log
656 const std::string ibus_daemon_command_line = 655 const std::string ibus_daemon_command_line =
657 StringPrintf("%s --panel=disable --cache=none --restart --replace", 656 StringPrintf("%s --panel=disable --cache=none --restart --replace",
658 kIBusDaemonPath); 657 kIBusDaemonPath);
659 if (!LaunchInputMethodProcess( 658 if (!LaunchInputMethodProcess(
660 ibus_daemon_command_line, &ibus_daemon_process_id_)) { 659 ibus_daemon_command_line, &ibus_daemon_process_handle_)) {
661 LOG(ERROR) << "Failed to launch " << ibus_daemon_command_line; 660 LOG(ERROR) << "Failed to launch " << ibus_daemon_command_line;
662 } 661 }
663 } 662 }
664 } 663 }
665 664
666 // Called when the input method process is shut down. 665 // Called when the input method process is shut down.
667 static void OnImeShutdown(int pid, 666 static void OnImeShutdown(GPid pid,
668 int status, 667 gint status,
669 InputMethodLibraryImpl* library) { 668 InputMethodLibraryImpl* library) {
670 g_spawn_close_pid(pid); 669 if (library->ibus_daemon_process_handle_ != base::kNullProcessHandle &&
671 if (library->ibus_daemon_process_id_ == pid) { 670 base::GetProcId(library->ibus_daemon_process_handle_) == pid) {
672 library->ibus_daemon_process_id_ = 0; 671 library->ibus_daemon_process_handle_ = base::kNullProcessHandle;
673 } 672 }
674 673
675 // Restart input method daemon if needed. 674 // Restart input method daemon if needed.
676 library->MaybeLaunchInputMethodDaemon(); 675 library->MaybeLaunchInputMethodDaemon();
677 } 676 }
678 677
679 // Stops the backend input method daemon. This function should also be 678 // Stops the backend input method daemon. This function should also be
680 // called from MaybeStopInputMethodDaemon(), except one case where we 679 // called from MaybeStopInputMethodDaemon(), except one case where we
681 // stop the input method daemon at Chrome shutdown in Observe(). 680 // stop the input method daemon at Chrome shutdown in Observe().
682 void StopInputMethodDaemon() { 681 void StopInputMethodDaemon() {
683 if (!initialized_successfully_) 682 if (!initialized_successfully_)
684 return; 683 return;
685 684
686 should_launch_ime_ = false; 685 should_launch_ime_ = false;
687 if (ibus_daemon_process_id_) { 686 if (ibus_daemon_process_handle_ != base::kNullProcessHandle) {
687 const base::ProcessId pid = base::GetProcId(ibus_daemon_process_handle_);
688 if (!chromeos::StopInputMethodProcess(input_method_status_connection_)) { 688 if (!chromeos::StopInputMethodProcess(input_method_status_connection_)) {
689 LOG(ERROR) << "StopInputMethodProcess IPC failed. Sending SIGTERM to " 689 LOG(ERROR) << "StopInputMethodProcess IPC failed. Sending SIGTERM to "
690 << "PID " << ibus_daemon_process_id_; 690 << "PID " << pid;
691 kill(ibus_daemon_process_id_, SIGTERM); 691 base::KillProcess(ibus_daemon_process_handle_, -1, false /* wait */);
692 } 692 }
693 VLOG(1) << "ibus-daemon (PID=" << ibus_daemon_process_id_ << ") is " 693 VLOG(1) << "ibus-daemon (PID=" << pid << ") is terminated";
694 << "terminated"; 694 ibus_daemon_process_handle_ = base::kNullProcessHandle;
695 ibus_daemon_process_id_ = 0;
696 } 695 }
697 } 696 }
698 697
699 void SetDeferImeStartup(bool defer) { 698 void SetDeferImeStartup(bool defer) {
700 VLOG(1) << "Setting DeferImeStartup to " << defer; 699 VLOG(1) << "Setting DeferImeStartup to " << defer;
701 defer_ime_startup_ = defer; 700 defer_ime_startup_ = defer;
702 } 701 }
703 702
704 void SetEnableAutoImeShutdown(bool enable) { 703 void SetEnableAutoImeShutdown(bool enable) {
705 enable_auto_ime_shutdown_ = enable; 704 enable_auto_ime_shutdown_ = enable;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
758 bool enable_auto_ime_shutdown_; 757 bool enable_auto_ime_shutdown_;
759 // The ID of the tentative current input method (ex. "mozc"). This value 758 // The ID of the tentative current input method (ex. "mozc"). This value
760 // can be different from the actual current input method, if 759 // can be different from the actual current input method, if
761 // ChangeInputMethod() fails. 760 // ChangeInputMethod() fails.
762 std::string tentative_current_input_method_id_; 761 std::string tentative_current_input_method_id_;
763 // True if we should change the current input method to 762 // True if we should change the current input method to
764 // |tentative_current_input_method_id_| once the queue of the pending config 763 // |tentative_current_input_method_id_| once the queue of the pending config
765 // requests becomes empty. 764 // requests becomes empty.
766 bool should_change_input_method_; 765 bool should_change_input_method_;
767 766
768 // The process id of the IBus daemon. 0 if it's not running. The process 767 // 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. 768 // running.
770 int ibus_daemon_process_id_; 769 base::ProcessHandle ibus_daemon_process_handle_;
771 770
772 // True if initialization is successfully done, meaning that libcros is 771 // True if initialization is successfully done, meaning that libcros is
773 // loaded and input method status monitoring is started. This value 772 // loaded and input method status monitoring is started. This value
774 // should be checked where we call libcros functions. 773 // should be checked where we call libcros functions.
775 bool initialized_successfully_; 774 bool initialized_successfully_;
776 775
777 // The candidate window. This will be deleted when the APP_TERMINATING 776 // The candidate window. This will be deleted when the APP_TERMINATING
778 // message is sent. 777 // message is sent.
779 scoped_ptr<CandidateWindowController> candidate_window_controller_; 778 scoped_ptr<CandidateWindowController> candidate_window_controller_;
780 779
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
1100 } 1099 }
1101 return impl; 1100 return impl;
1102 } 1101 }
1103 } 1102 }
1104 1103
1105 } // namespace chromeos 1104 } // namespace chromeos
1106 1105
1107 // Allows InvokeLater without adding refcounting. This class is a Singleton and 1106 // Allows InvokeLater without adding refcounting. This class is a Singleton and
1108 // won't be deleted until it's last InvokeLater is run. 1107 // won't be deleted until it's last InvokeLater is run.
1109 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::InputMethodLibraryImpl); 1108 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