summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorjamiewalch@chromium.org <jamiewalch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-12 09:01:32 +0000
committerjamiewalch@chromium.org <jamiewalch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-12 09:01:32 +0000
commitc8abf3d5169d5e139443eed29d500cfba2127346 (patch)
tree61fc9c9720325a5cf1896a1f3e0c865dbad41591 /remoting
parentb36fcd0ba0372bd4b67e6b9dcb05704753189f03 (diff)
downloadchromium_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.cc6
-rw-r--r--remoting/host/plugin/daemon_controller_mac.cc32
-rw-r--r--remoting/host/remoting_me2me_host.cc48
-rw-r--r--remoting/host/sighup_listener_mac.cc93
-rw-r--r--remoting/host/sighup_listener_mac.h22
-rw-r--r--remoting/remoting.gyp2
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': [