Index: chrome/browser/chromeos/input_method/ibus_controller_impl.cc |
diff --git a/chrome/browser/chromeos/input_method/ibus_controller_impl.cc b/chrome/browser/chromeos/input_method/ibus_controller_impl.cc |
index 10a354a9e7c5bb725a9d1c61288aaa4b0ce4fbb1..1af04158819255ee58b7653c5cbce11384b46282 100644 |
--- a/chrome/browser/chromeos/input_method/ibus_controller_impl.cc |
+++ b/chrome/browser/chromeos/input_method/ibus_controller_impl.cc |
@@ -12,12 +12,19 @@ |
#include <stack> |
#include <utility> |
+#include "base/bind.h" |
+#include "base/environment.h" |
+#include "base/files/file_path_watcher.h" |
#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop.h" |
+#include "base/rand_util.h" |
#include "base/stringprintf.h" |
#include "base/string_split.h" |
#include "chrome/browser/chromeos/input_method/input_method_config.h" |
#include "chrome/browser/chromeos/input_method/input_method_property.h" |
#include "chrome/browser/chromeos/input_method/input_method_util.h" |
+#include "chromeos/dbus/dbus_thread_manager.h" |
+#include "content/public/browser/browser_thread.h" |
// TODO(nona): Remove libibus dependency from this file. Then, write unit tests |
// for all functions in this file. crbug.com/26334 |
@@ -357,13 +364,68 @@ std::string PrintPropList(IBusPropList *prop_list, int tree_level) { |
return stream.str(); |
} |
+// The implementation of FilePathWatcher::Delegate, used in |
+// StartAddressFileWatch function. |
+class IBusAddressFileWatcherDelegate |
+ : public base::files::FilePathWatcher::Delegate { |
+ public: |
+ IBusAddressFileWatcherDelegate(const std::string& ibus_address, |
+ base::files::FilePathWatcher* watcher, |
+ IBusControllerImpl* controller) |
+ : ibus_address_(ibus_address), |
+ watcher_(watcher), |
+ controller_(controller) { |
+ } |
+ |
+ virtual ~IBusAddressFileWatcherDelegate() {} |
+ |
+ virtual void OnFilePathChanged(const FilePath& file_path) { |
+ content::BrowserThread::PostTaskAndReply( |
Yusuke Sato
2012/04/27 02:12:13
check return value?
Seigo Nonaka
2012/05/01 00:19:54
Done.
|
+ content::BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&chromeos::DBusThreadManager::MaybeResetIBusBus, |
+ base::Unretained(chromeos::DBusThreadManager::Get()), |
+ ibus_address_), |
+ base::Bind(&IBusControllerImpl::IBusBusInitializationDone, |
Yusuke Sato
2012/04/27 02:12:13
flipping the flag from FILE thread w/o locking loo
Seigo Nonaka
2012/05/01 00:19:54
Done.
|
+ controller_)); |
+ MessageLoop::current()->DeleteSoon(FROM_HERE, watcher_); |
+ } |
+ |
+ private: |
+ // The ibus-daemon address. |
+ const std::string ibus_address_; |
+ |
Yusuke Sato
2012/04/27 02:12:13
nit: add a comment or remove this line.
Seigo Nonaka
2012/05/01 00:19:54
Done.
|
+ IBusControllerImpl* controller_; |
+ |
Yusuke Sato
2012/04/27 02:12:13
nit: the same as above.
Seigo Nonaka
2012/05/01 00:19:54
Done.
|
+ base::files::FilePathWatcher* watcher_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(IBusAddressFileWatcherDelegate); |
+}; |
+ |
+void StartAddressFileWatch(const std::string& ibus_address, |
+ IBusControllerImpl* controller) { |
+ scoped_ptr<base::Environment> env(base::Environment::Create()); |
+ std::string address_file_path; |
+ env->GetVar("IBUS_ADDRESS_FILE", &address_file_path); |
Yusuke Sato
2012/04/27 02:12:13
DCHECK(!address_file_path.empty());
Seigo Nonaka
2012/05/01 00:19:54
Done.
|
+ |
+ // The |watcher| instance will be released by |delegate|. |
+ base::files::FilePathWatcher* watcher = new base::files::FilePathWatcher; |
+ |
+ // The |delegate| is owned by watcher. |
+ IBusAddressFileWatcherDelegate* delegate = new IBusAddressFileWatcherDelegate( |
+ ibus_address, watcher, controller); |
+ bool result = watcher->Watch(FilePath(address_file_path), delegate); |
+ DCHECK(result); |
+} |
} // namespace |
IBusControllerImpl::IBusControllerImpl() |
: ibus_(NULL), |
ibus_config_(NULL), |
should_launch_daemon_(false), |
- process_handle_(base::kNullProcessHandle) { |
+ process_handle_(base::kNullProcessHandle), |
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), |
+ is_initializing_ibus_daemon_(false) { |
} |
IBusControllerImpl::~IBusControllerImpl() { |
@@ -893,8 +955,6 @@ void IBusControllerImpl::UpdateProperty(IBusPanelService* panel, |
} |
bool IBusControllerImpl::MaybeLaunchIBusDaemon() { |
- static const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon"; |
- |
if (process_handle_ != base::kNullProcessHandle) { |
DVLOG(1) << "MaybeLaunchIBusDaemon: ibus-daemon is already running."; |
return false; |
@@ -902,17 +962,39 @@ bool IBusControllerImpl::MaybeLaunchIBusDaemon() { |
if (!should_launch_daemon_) |
return false; |
+ if (is_initializing_ibus_daemon_) |
+ return false; |
+ |
+ is_initializing_ibus_daemon_ = true; |
+ const std::string ibus_address = base::StringPrintf( |
+ "unix:abstract=/tmp/ibus-%0lX", base::RandUint64()); |
+ |
+ // Set up ibus-daemon address file watcher before launching ibus-daemon, |
+ // because if watcher start after ibus-daemon, we may miss the ibus connection |
+ // initialization. |
+ content::BrowserThread::PostTaskAndReply( |
Yusuke Sato
2012/04/27 02:12:13
check return value?
Seigo Nonaka
2012/05/01 00:19:54
Done.
|
+ content::BrowserThread::FILE, |
+ FROM_HERE, |
+ base::Bind(&StartAddressFileWatch, ibus_address), |
+ base::Bind(&IBusControllerImpl::LaunchIBusDaemon, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ ibus_address)); |
+ return true; |
+} |
+ |
+void IBusControllerImpl::LaunchIBusDaemon(const std::string& ibus_address) { |
+ static const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon"; |
// TODO(zork): Send output to /var/log/ibus.log |
const std::string ibus_daemon_command_line = |
- base::StringPrintf("%s --panel=disable --cache=none --restart --replace", |
- kIBusDaemonPath); |
+ base::StringPrintf("%s --panel=disable --cache=none --restart --replace" |
+ " --address=%s", |
+ kIBusDaemonPath, |
+ ibus_address.c_str()); |
if (!LaunchProcess(ibus_daemon_command_line, |
&process_handle_, |
reinterpret_cast<GChildWatchFunc>(OnIBusDaemonExit))) { |
DVLOG(1) << "Failed to launch " << ibus_daemon_command_line; |
- return false; |
} |
- return true; |
} |
bool IBusControllerImpl::LaunchProcess(const std::string& command_line, |
@@ -939,6 +1021,10 @@ bool IBusControllerImpl::LaunchProcess(const std::string& command_line, |
return true; |
} |
+void IBusControllerImpl::IBusDaemonInitializationDone() { |
+ is_initializing_ibus_daemon_ = false; |
+} |
+ |
// static |
void IBusControllerImpl::SetInputMethodConfigCallback(GObject* source_object, |
GAsyncResult* res, |