diff options
author | jamiewalch@chromium.org <jamiewalch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-12 09:01:32 +0000 |
---|---|---|
committer | jamiewalch@chromium.org <jamiewalch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-12 09:01:32 +0000 |
commit | c8abf3d5169d5e139443eed29d500cfba2127346 (patch) | |
tree | 61fc9c9720325a5cf1896a1f3e0c865dbad41591 /remoting | |
parent | b36fcd0ba0372bd4b67e6b9dcb05704753189f03 (diff) | |
download | chromium_src-c8abf3d5169d5e139443eed29d500cfba2127346.zip chromium_src-c8abf3d5169d5e139443eed29d500cfba2127346.tar.gz chromium_src-c8abf3d5169d5e139443eed29d500cfba2127346.tar.bz2 |
Implemented updateConfig for Mac.
BUG=121530
TEST=Manual
Review URL: http://codereview.chromium.org/9999014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@131956 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/host/plugin/daemon_controller_linux.cc | 6 | ||||
-rw-r--r-- | remoting/host/plugin/daemon_controller_mac.cc | 32 | ||||
-rw-r--r-- | remoting/host/remoting_me2me_host.cc | 48 | ||||
-rw-r--r-- | remoting/host/sighup_listener_mac.cc | 93 | ||||
-rw-r--r-- | remoting/host/sighup_listener_mac.h | 22 | ||||
-rw-r--r-- | remoting/remoting.gyp | 2 |
6 files changed, 191 insertions, 12 deletions
diff --git a/remoting/host/plugin/daemon_controller_linux.cc b/remoting/host/plugin/daemon_controller_linux.cc index d68be8a..1a8f45c 100644 --- a/remoting/host/plugin/daemon_controller_linux.cc +++ b/remoting/host/plugin/daemon_controller_linux.cc @@ -224,14 +224,16 @@ void DaemonControllerLinux::DoUpdateConfig( scoped_ptr<base::DictionaryValue> config, const CompletionCallback& done_callback) { JsonHostConfig config_file(GetConfigPath()); - if (!config_file.Read()) + if (!config_file.Read()) { done_callback.Run(RESULT_FAILED); + } for (DictionaryValue::key_iterator key(config->begin_keys()); key != config->end_keys(); ++key) { std::string value; if (!config->GetString(*key, &value)) { - LOG(WARNING) << "Skipping " << *key << " because it is not a string."; + LOG(ERROR) << *key << " is not a string."; + done_callback.Run(RESULT_FAILED); } config_file.SetString(*key, value); } diff --git a/remoting/host/plugin/daemon_controller_mac.cc b/remoting/host/plugin/daemon_controller_mac.cc index d22b204..b48d7ec 100644 --- a/remoting/host/plugin/daemon_controller_mac.cc +++ b/remoting/host/plugin/daemon_controller_mac.cc @@ -68,6 +68,8 @@ class DaemonControllerMac : public remoting::DaemonController { void DoGetConfig(const GetConfigCallback& callback); void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, const CompletionCallback& done_callback); + void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config, + const CompletionCallback& done_callback); void DoStop(const CompletionCallback& done_callback); void NotifyWhenStopped(const CompletionCallback& done_callback, int tries_remaining, @@ -132,8 +134,9 @@ void DaemonControllerMac::SetConfigAndStart( void DaemonControllerMac::UpdateConfig( scoped_ptr<base::DictionaryValue> config, const CompletionCallback& done_callback) { - NOTIMPLEMENTED(); - done_callback.Run(RESULT_FAILED); + auth_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( + &DaemonControllerMac::DoUpdateConfig, base::Unretained(this), + base::Passed(&config), done_callback)); } void DaemonControllerMac::Stop(const CompletionCallback& done_callback) { @@ -183,6 +186,31 @@ void DaemonControllerMac::DoSetConfigAndStart( done_callback.Run(result ? RESULT_OK : RESULT_FAILED); } +void DaemonControllerMac::DoUpdateConfig( + scoped_ptr<base::DictionaryValue> config, + const CompletionCallback& done_callback) { + FilePath config_file_path(kHostConfigFile); + JsonHostConfig config_file(config_file_path); + if (!config_file.Read()) { + done_callback.Run(RESULT_FAILED); + } + for (DictionaryValue::key_iterator key(config->begin_keys()); + key != config->end_keys(); ++key) { + std::string value; + if (!config->GetString(*key, &value)) { + LOG(ERROR) << *key << " is not a string."; + done_callback.Run(RESULT_FAILED); + } + config_file.SetString(*key, value); + } + bool success = config_file.Save(); + done_callback.Run(success ? RESULT_OK : RESULT_FAILED); + pid_t job_pid = base::mac::PIDForJob(kServiceName); + if (job_pid > 0) { + kill(job_pid, SIGHUP); + } +} + void DaemonControllerMac::DoStop(const CompletionCallback& done_callback) { if (!RunToolScriptAsRoot("--disable")) { done_callback.Run(RESULT_FAILED); diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index 885f7a0..6e1d57a 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// This file implements a standalone host process for Me2Me, which is currently -// used for the Linux-only Virtual Me2Me build. +// This file implements a standalone host process for Me2Me. #if defined(OS_WIN) #include <windows.h> @@ -42,6 +41,9 @@ #include "remoting/jingle_glue/xmpp_signal_strategy.h" #include "remoting/protocol/me2me_host_authenticator_factory.h" +#if defined(OS_MACOSX) +#include "remoting/host/sighup_listener_mac.h" +#endif #if defined(TOOLKIT_GTK) #include "ui/gfx/gtk_util.h" #endif @@ -104,6 +106,35 @@ class HostProcess : public OAuthClient::Delegate { #endif } + void ConfigUpdated() { + // The auth tokens can't be updated once the host is running, so we don't + // need to check the pending state, but it's a required parameter. + bool tokens_pending; + if (LoadConfig(file_io_thread_.message_loop_proxy(), &tokens_pending)) { + context_->network_message_loop()->PostTask( + FROM_HERE, + base::Bind(&HostProcess::CreateAuthenticatorFactory, + base::Unretained(this))); + } else { + LOG(ERROR) << "Invalid configuration."; + } + } + +#if defined(OS_MACOSX) + void ListenForConfigChanges() { + remoting::RegisterHupSignalHandler( + base::Bind(&HostProcess::ConfigUpdated, base::Unretained(this))); + } +#endif + + void CreateAuthenticatorFactory() { + scoped_ptr<protocol::AuthenticatorFactory> factory( + new protocol::Me2MeHostAuthenticatorFactory( + xmpp_login_, key_pair_.GenerateCertificate(), + *key_pair_.private_key(), host_secret_hash_)); + host_->SetAuthenticatorFactory(factory.Pass()); + } + int Run() { bool tokens_pending = false; if (!LoadConfig(file_io_thread_.message_loop_proxy(), &tokens_pending)) { @@ -120,6 +151,12 @@ class HostProcess : public OAuthClient::Delegate { StartWatchingNatPolicy(); } +#if defined(OS_MACOSX) + file_io_thread_.message_loop_proxy()->PostTask( + FROM_HERE, + base::Bind(&HostProcess::ListenForConfigChanges, + base::Unretained(this))); +#endif message_loop_.Run(); return 0; @@ -270,12 +307,7 @@ class HostProcess : public OAuthClient::Delegate { host_->Start(); - // Create authenticator factory. - scoped_ptr<protocol::AuthenticatorFactory> factory( - new protocol::Me2MeHostAuthenticatorFactory( - xmpp_login_, key_pair_.GenerateCertificate(), - *key_pair_.private_key(), host_secret_hash_)); - host_->SetAuthenticatorFactory(factory.Pass()); + CreateAuthenticatorFactory(); } void RestartHost() { diff --git a/remoting/host/sighup_listener_mac.cc b/remoting/host/sighup_listener_mac.cc new file mode 100644 index 0000000..9613ba2 --- /dev/null +++ b/remoting/host/sighup_listener_mac.cc @@ -0,0 +1,93 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// TODO(jamiewalch): Add unit tests for this. + +#include "remoting/host/sighup_listener_mac.h" + +#include <errno.h> + +#include "base/compiler_specific.h" +#include "base/eintr_wrapper.h" +#include "base/message_loop.h" +#include "base/message_pump_libevent.h" +#include "base/threading/platform_thread.h" + +namespace { + +class SigHupListener : public base::MessagePumpLibevent::Watcher { + public: + SigHupListener(const base::Closure& callback); + + virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; + virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {} + + // WatchFileDescriptor needs a controller through which the operation can be + // canceled. We don't use it, but this is as good a place as any to store it. + base::MessagePumpLibevent::FileDescriptorWatcher controller; + + private: + base::Closure callback_; +}; + +SigHupListener::SigHupListener(const base::Closure& callback) + : callback_(callback) { +} + +void SigHupListener::OnFileCanReadWithoutBlocking(int fd) { + char buffer; + int result = HANDLE_EINTR(read(fd, &buffer, sizeof(buffer))); + if (result > 0) { + callback_.Run(); + } +} + +SigHupListener* g_config_updater = NULL; +int g_write_fd = 0; + +void HupSignalHandler(int signal) { + int r ALLOW_UNUSED = write(g_write_fd, "", 1); +} + +} // namespace + +namespace remoting { + +// RegisterHupSignalHandler registers a signal handler that writes a byte to a +// pipe each time SIGHUP is received. The read end of the pipe is registered +// with the current MessageLoop (which must be of type IO); whenever the pipe +// is readable, it invokes the specified callback. +// +// This arrangement is required because the set of system APIs that are safe to +// call from a singal handler is very limited (but does include write). +bool RegisterHupSignalHandler(const base::Closure& callback) { + DCHECK(!g_config_updater); + MessageLoopForIO* message_loop = MessageLoopForIO::current(); + int pipefd[2]; + int result = pipe(pipefd); + if (result < 0) { + LOG(ERROR) << "Could not create SIGHUP pipe: " << errno; + return false; + } + g_write_fd = pipefd[1]; + g_config_updater = new SigHupListener(callback); + result = message_loop->WatchFileDescriptor( + pipefd[0], true, MessageLoopForIO::WATCH_READ, + &g_config_updater->controller, g_config_updater); + if (!result) { + delete g_config_updater; + g_config_updater = NULL; + LOG(ERROR) << "Failed to create SIGHUP detector task."; + return false; + } + if (signal(SIGHUP, HupSignalHandler) == SIG_ERR) { + delete g_config_updater; + g_config_updater = NULL; + LOG(ERROR) << "signal() failed: " << errno; + return false; + } + return true; +} + +} // namespace remoting diff --git a/remoting/host/sighup_listener_mac.h b/remoting/host/sighup_listener_mac.h new file mode 100644 index 0000000..d9b87e9 --- /dev/null +++ b/remoting/host/sighup_listener_mac.h @@ -0,0 +1,22 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// This file implements a signal handler that is used to safely handle SIGHUP +// and trigger the specified callback. It is currently used on Mac in order to +// reload the me2me host configuration, but would need minimal changes on Linux. + +#ifndef REMOTING_SIGHUP_LISTENER_MAC_H_ +#define REMOTING_SIGHUP_LISTENER_MAC_H_ + +#include "base/callback_forward.h" + +namespace remoting { + +// Register for SIGHUP notifications on the current thread, which must have +// an associated MessageLoopForIO. +bool RegisterHupSignalHandler(const base::Closure& callback); + +} // namespace remoting + +#endif // REMOTING_SIGHUP_LISTENER_MAC_H_ diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 1a4405e..47a7381 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -1009,6 +1009,8 @@ 'host/branding.cc', 'host/branding.h', 'host/host_event_logger.h', + 'host/sighup_listener_mac.cc', + 'host/sighup_listener_mac.h', 'host/remoting_me2me_host.cc', ], 'conditions': [ |