summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--remoting/DEPS2
-rw-r--r--remoting/base/constants.cc2
-rw-r--r--remoting/host/chromoting_host.cc15
-rw-r--r--remoting/host/chromoting_host.h9
-rw-r--r--remoting/host/heartbeat_sender.cc9
-rw-r--r--remoting/host/heartbeat_sender.h7
-rw-r--r--remoting/host/host_config.cc15
-rw-r--r--remoting/host/host_config.h97
-rw-r--r--remoting/host/json_host_config.cc64
-rw-r--r--remoting/host/json_host_config.h59
-rw-r--r--remoting/host/json_host_config_unittest.cc121
-rw-r--r--remoting/host/session_manager.h8
-rw-r--r--remoting/host/simple_host_process.cc91
-rw-r--r--remoting/remoting.gyp5
-rw-r--r--remoting/tools/gaia_auth.py29
-rwxr-xr-xremoting/tools/gettoken.py48
-rwxr-xr-xremoting/tools/register_host.py83
17 files changed, 509 insertions, 155 deletions
diff --git a/remoting/DEPS b/remoting/DEPS
index 46cb98b..d446efa 100644
--- a/remoting/DEPS
+++ b/remoting/DEPS
@@ -1,5 +1,5 @@
include_rules = [
- "+chrome/common/net",
+ "+chrome/common",
"+gfx",
"+google/protobuf",
"+media/base",
diff --git a/remoting/base/constants.cc b/remoting/base/constants.cc
index 6618eb7..0255200 100644
--- a/remoting/base/constants.cc
+++ b/remoting/base/constants.cc
@@ -6,7 +6,7 @@
namespace remoting {
-const std::string kChromotingBotJid("chromoting@bot.talk.google.com");
+const std::string kChromotingBotJid("remoting@bot.talk.google.com");
// TODO(sergeyu): Use chromoting's own service name here instead of sync.
const std::string kChromotingTokenServiceName("chromiumsync");
diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc
index 9679442..0fc60e2 100644
--- a/remoting/host/chromoting_host.cc
+++ b/remoting/host/chromoting_host.cc
@@ -15,7 +15,7 @@
namespace remoting {
-ChromotingHost::ChromotingHost(HostConfig* config,
+ChromotingHost::ChromotingHost(MutableHostConfig* config,
Capturer* capturer,
Encoder* encoder,
EventExecutor* executor,
@@ -80,9 +80,17 @@ void ChromotingHost::RegisterHost() {
DCHECK_EQ(message_loop(), MessageLoop::current());
DCHECK(!jingle_client_);
+ std::string xmpp_login;
+ std::string xmpp_auth_token;
+ if (!config_->GetString(kXmppLoginConfigPath, &xmpp_login) ||
+ !config_->GetString(kXmppAuthTokenConfigPath, &xmpp_auth_token)) {
+ LOG(ERROR) << "XMMP credentials are not defined in config.";
+ return;
+ }
+
// Connect to the talk network with a JingleClient.
jingle_client_ = new JingleClient(&network_thread_);
- jingle_client_->Init(config_->xmpp_login(), config_->xmpp_auth_token(),
+ jingle_client_->Init(xmpp_login, xmpp_auth_token,
kChromotingTokenServiceName, this);
}
@@ -184,13 +192,14 @@ void ChromotingHost::OnStateChange(JingleClient* jingle_client,
// Start heartbeating after we connected
heartbeat_sender_ = new HeartbeatSender();
- // TODO(sergeyu): where do we get host id?
heartbeat_sender_->Start(config_, jingle_client_.get());
} else if (state == JingleClient::CLOSED) {
LOG(INFO) << "Host disconnected from talk network." << std::endl;
heartbeat_sender_ = NULL;
// Quit the message loop if disconected.
+ // TODO(sergeyu): We should try reconnecting here instead of terminating
+ // the host.
message_loop()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
host_done_->Signal();
}
diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h
index 6b00b2e..930bf89 100644
--- a/remoting/host/chromoting_host.h
+++ b/remoting/host/chromoting_host.h
@@ -23,7 +23,7 @@ class WaitableEvent;
namespace remoting {
-class HostConfig;
+class MutableHostConfig;
// A class to implement the functionality of a host process.
//
@@ -54,8 +54,9 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>,
public ClientConnection::EventHandler,
public JingleClient::Callback {
public:
- ChromotingHost(HostConfig* config, Capturer* capturer, Encoder* encoder,
- EventExecutor* executor, base::WaitableEvent* host_done);
+ ChromotingHost(MutableHostConfig* config, Capturer* capturer,
+ Encoder* encoder, EventExecutor* executor,
+ base::WaitableEvent* host_done);
virtual ~ChromotingHost();
// Run the host porcess. This method returns only after the message loop
@@ -109,7 +110,7 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>,
// A thread that hosts encode operations.
base::Thread encode_thread_;
- scoped_refptr<HostConfig> config_;
+ scoped_refptr<MutableHostConfig> config_;
// Capturer to be used by SessionManager. Once the SessionManager is
// constructed this is set to NULL.
diff --git a/remoting/host/heartbeat_sender.cc b/remoting/host/heartbeat_sender.cc
index 4ce45b6..fa234e3 100644
--- a/remoting/host/heartbeat_sender.cc
+++ b/remoting/host/heartbeat_sender.cc
@@ -29,7 +29,7 @@ HeartbeatSender::HeartbeatSender()
: started_(false) {
}
-void HeartbeatSender::Start(HostConfig* config, JingleClient* jingle_client) {
+void HeartbeatSender::Start(MutableHostConfig* config, JingleClient* jingle_client) {
DCHECK(jingle_client);
DCHECK(!started_);
@@ -38,6 +38,11 @@ void HeartbeatSender::Start(HostConfig* config, JingleClient* jingle_client) {
jingle_client_ = jingle_client;
config_ = config;
+ if (!config_->GetString(kHostIdConfigPath, &host_id_)) {
+ LOG(ERROR) << "host_id is not defined in the config.";
+ return;
+ }
+
jingle_client_->message_loop()->PostTask(
FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::DoStart));
}
@@ -58,7 +63,7 @@ void HeartbeatSender::DoSendStanza() {
LOG(INFO) << "Sending heartbeat stanza to " << kChromotingBotJid;
buzz::XmlElement* stanza = new buzz::XmlElement(kHeartbeatQuery);
- stanza->AddAttr(kHostIdAttr, config_->host_id());
+ stanza->AddAttr(kHostIdAttr, host_id_);
request_->SendIq(buzz::STR_SET, kChromotingBotJid, stanza);
// Schedule next heartbeat.
diff --git a/remoting/host/heartbeat_sender.h b/remoting/host/heartbeat_sender.h
index f11d21d..08665c6 100644
--- a/remoting/host/heartbeat_sender.h
+++ b/remoting/host/heartbeat_sender.h
@@ -15,7 +15,7 @@ namespace remoting {
class IqRequest;
class JingleClient;
-class HostConfig;
+class MutableHostConfig;
// HeartbeatSender periodically sends hertbeats to the chromoting bot.
// TODO(sergeyu): Write unittest for this class.
@@ -24,7 +24,7 @@ class HeartbeatSender : public base::RefCountedThreadSafe<HeartbeatSender> {
HeartbeatSender();
// Starts heart-beating for |jingle_client|.
- void Start(HostConfig* config, JingleClient* jingle_client);
+ void Start(MutableHostConfig* config, JingleClient* jingle_client);
private:
void DoStart();
@@ -33,9 +33,10 @@ class HeartbeatSender : public base::RefCountedThreadSafe<HeartbeatSender> {
void ProcessResponse(const buzz::XmlElement* response);
bool started_;
- scoped_refptr<HostConfig> config_;
+ scoped_refptr<MutableHostConfig> config_;
JingleClient* jingle_client_;
scoped_ptr<IqRequest> request_;
+ std::string host_id_;
};
} // namespace remoting
diff --git a/remoting/host/host_config.cc b/remoting/host/host_config.cc
new file mode 100644
index 0000000..1ce16dc
--- /dev/null
+++ b/remoting/host/host_config.cc
@@ -0,0 +1,15 @@
+// Copyright (c) 2010 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.
+
+#include "remoting/host/host_config.h"
+
+namespace remoting {
+
+const std::wstring kXmppLoginConfigPath(L"xmpp_login");
+const std::wstring kXmppAuthTokenConfigPath(L"xmpp_auth_token");
+const std::wstring kHostIdConfigPath(L"host_id");
+const std::wstring kHostNameConfigPath(L"host_name");
+const std::wstring kPublicKeyConfigPath(L"public_key");
+
+} // namespace remoting
diff --git a/remoting/host/host_config.h b/remoting/host/host_config.h
index b0eb382..7897538 100644
--- a/remoting/host/host_config.h
+++ b/remoting/host/host_config.h
@@ -9,69 +9,58 @@
#include "base/ref_counted.h"
+class Task;
+
namespace remoting {
-// HostConfig class implements container for all host settings.
+// Following constants define names for configuration parameters.
+
+// Login used to authenticate in XMPP network.
+extern const std::wstring kXmppLoginConfigPath;
+// Auth token used to authenticate in XMPP network.
+extern const std::wstring kXmppAuthTokenConfigPath;
+// Unique identifier of the host used to register the host in directory.
+// Normally a random UUID.
+extern const std::wstring kHostIdConfigPath;
+// Readable host name.
+extern const std::wstring kHostNameConfigPath;
+// Public key used by the host for authentication.
+extern const std::wstring kPublicKeyConfigPath;
+
+// TODO(sergeyu): Add a property for private key.
+
+// HostConfig interace provides read-only access to host configuration.
class HostConfig : public base::RefCountedThreadSafe<HostConfig> {
public:
- HostConfig() { }
-
- // Login used to authenticate in XMPP network.
- const std::string& xmpp_login() const {
- return xmpp_login_;
- }
- void set_xmpp_login(const std::string& xmpp_login) {
- xmpp_login_ = xmpp_login;
- }
-
- // Auth token used to authenticate in XMPP network.
- const std::string& xmpp_auth_token() const {
- return xmpp_auth_token_;
- }
- void set_xmpp_auth_token(const std::string& xmpp_auth_token) {
- xmpp_auth_token_ = xmpp_auth_token;
- }
-
- // Unique identifier of the host used to register the host in directory.
- // Normally a random UUID.
- const std::string& host_id() const {
- return host_id_;
- }
- void set_host_id(const std::string& host_id) {
- host_id_ = host_id;
- }
-
- // Public key used by the host for authentication.
- // TODO(sergeyu): Do we need to use other type to store public key? E.g.
- // DataBuffer? Revisit this when public key generation is implemented.
- const std::string& public_key() const {
- return public_key_;
- }
- void set_public_key(const std::string& public_key) {
- public_key_ = public_key;
- }
-
- // TODO(sergeyu): Add a property for private key.
-
- private:
- std::string xmpp_login_;
- std::string xmpp_auth_token_;
- std::string host_id_;
- std::string public_key_;
+ HostConfig() { };
+ virtual ~HostConfig() { }
+
+ virtual bool GetString(const std::wstring& path,
+ std::wstring* out_value) = 0;
+ virtual bool GetString(const std::wstring& path,
+ std::string* out_value) = 0;
DISALLOW_COPY_AND_ASSIGN(HostConfig);
};
-// Interface for host configuration storage provider.
-class HostConfigStorage {
- // Load() and Save() are used to load/save settings to/from permanent
- // storage. For example FileHostConfig stores all settings in a file.
- // Simularly RegistryHostConfig stores settings in windows registry.
- // Both methods return false if operation has failed, true otherwise.
- virtual bool Load(HostConfig* config) = 0;
- virtual bool Save(const HostConfig& config) = 0;
+// MutableHostConfig extends HostConfig for mutability.
+class MutableHostConfig : public HostConfig {
+ public:
+ MutableHostConfig() { };
+
+ // Update() must be used to update config values.
+ // It acquires lock, calls the specified task, releases the lock and
+ // then schedules the config to be written to storage.
+ virtual void Update(Task* task) = 0;
+
+ // SetString() updates specified config value. This methods must only
+ // be called from task specified in Update().
+ virtual void SetString(const std::wstring& path,
+ const std::wstring& in_value) = 0;
+ virtual void SetString(const std::wstring& path,
+ const std::string& in_value) = 0;
- DISALLOW_COPY_AND_ASSIGN(HostConfigStorage);
+ DISALLOW_COPY_AND_ASSIGN(MutableHostConfig);
};
} // namespace remoting
diff --git a/remoting/host/json_host_config.cc b/remoting/host/json_host_config.cc
new file mode 100644
index 0000000..324b2d2
--- /dev/null
+++ b/remoting/host/json_host_config.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2010 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.
+
+#include "remoting/host/json_host_config.h"
+
+#include "base/message_loop_proxy.h"
+#include "base/task.h"
+#include "base/values.h"
+#include "chrome/common/json_pref_store.h"
+#include "chrome/common/pref_store.h"
+
+namespace remoting {
+
+JsonHostConfig::JsonHostConfig(
+ const FilePath& filename,
+ base::MessageLoopProxy* file_message_loop_proxy)
+ : pref_store_(new JsonPrefStore(filename, file_message_loop_proxy)),
+ message_loop_proxy_(file_message_loop_proxy) {
+}
+
+bool JsonHostConfig::Read() {
+ return pref_store_->ReadPrefs() == PrefStore::PREF_READ_ERROR_NONE;
+}
+
+bool JsonHostConfig::GetString(const std::wstring& path,
+ std::wstring* out_value) {
+ AutoLock auto_lock(lock_);
+ return pref_store_->prefs()->GetString(path, out_value);
+}
+
+bool JsonHostConfig::GetString(const std::wstring& path,
+ std::string* out_value) {
+ AutoLock auto_lock(lock_);
+ return pref_store_->prefs()->GetString(path, out_value);
+}
+
+void JsonHostConfig::Update(Task* task) {
+ {
+ AutoLock auto_lock(lock_);
+ task->Run();
+ }
+ message_loop_proxy_->PostTask(
+ FROM_HERE, NewRunnableMethod(this, &JsonHostConfig::DoWrite));
+}
+
+void JsonHostConfig::SetString(const std::wstring& path,
+ const std::wstring& in_value) {
+ lock_.AssertAcquired();
+ pref_store_->prefs()->SetString(path, in_value);
+}
+
+void JsonHostConfig::SetString(const std::wstring& path,
+ const std::string& in_value) {
+ lock_.AssertAcquired();
+ pref_store_->prefs()->SetString(path, in_value);
+}
+
+void JsonHostConfig::DoWrite() {
+ AutoLock auto_lock(lock_);
+ pref_store_->WritePrefs();
+}
+
+} // namespace remoting
diff --git a/remoting/host/json_host_config.h b/remoting/host/json_host_config.h
new file mode 100644
index 0000000..ac10272
--- /dev/null
+++ b/remoting/host/json_host_config.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2010 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.
+
+#ifndef REMOTING_HOST_JSON_HOST_CONFIG_H_
+#define REMOTING_HOST_JSON_HOST_CONFIG_H_
+
+#include <string>
+
+#include "base/lock.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "remoting/host/host_config.h"
+
+class FilePath;
+class JsonPrefStore;
+class Task;
+
+namespace base {
+class MessageLoopProxy;
+} // namespace base
+
+namespace remoting {
+
+// JsonHostConfig implements MutableHostConfig for JSON file.
+class JsonHostConfig : public MutableHostConfig {
+ public:
+ JsonHostConfig(const FilePath& pref_filename,
+ base::MessageLoopProxy* file_message_loop_proxy);
+
+ virtual bool Read();
+
+ // MutableHostConfig interface.
+ virtual bool GetString(const std::wstring& path,
+ std::wstring* out_value);
+ virtual bool GetString(const std::wstring& path,
+ std::string* out_value);
+
+ virtual void Update(Task* task);
+
+ virtual void SetString(const std::wstring& path,
+ const std::wstring& in_value);
+ virtual void SetString(const std::wstring& path,
+ const std::string& in_value);
+
+ private:
+ void DoWrite();
+
+ // |lock_| must be locked whenever we access pref_store_;
+ Lock lock_;
+ scoped_ptr<JsonPrefStore> pref_store_;
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
+
+ DISALLOW_COPY_AND_ASSIGN(JsonHostConfig);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_HOST_JSON_HOST_CONFIG_H_
diff --git a/remoting/host/json_host_config_unittest.cc b/remoting/host/json_host_config_unittest.cc
new file mode 100644
index 0000000..ba6ce1b
--- /dev/null
+++ b/remoting/host/json_host_config_unittest.cc
@@ -0,0 +1,121 @@
+// Copyright (c) 2010 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.
+
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/path_service.h"
+#include "base/ref_counted.h"
+#include "base/scoped_temp_dir.h"
+#include "remoting/host/json_host_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace remoting {
+
+namespace {
+const char *kTestConfig =
+"{\n"
+" \"xmpp_login\" : \"test@gmail.com\",\n"
+" \"xmpp_auth_token\" : \"TEST_AUTH_TOKEN\",\n"
+" \"host_id\" : \"TEST_HOST_ID\",\n"
+" \"host_name\" : \"TEST_MACHINE_NAME\",\n"
+" \"public_key\" : \"TEST_PUBLIC_KEY\"\n"
+"}\n";
+
+// Helper for Update test.
+class TestConfigUpdater : public base::RefCountedThreadSafe<TestConfigUpdater> {
+ public:
+ void DoUpdate(scoped_refptr<JsonHostConfig> target,
+ std::string new_auth_token_value) {
+ target->SetString(kXmppAuthTokenConfigPath, new_auth_token_value);
+ }
+};
+} // namespace
+
+class JsonHostConfigTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ message_loop_proxy_ = base::MessageLoopProxy::CreateForCurrentThread();
+ }
+
+ static void WriteTestFile(const FilePath& filename) {
+ file_util::WriteFile(filename, kTestConfig, std::strlen(kTestConfig));
+ }
+
+ // The temporary directory used to contain the test operations.
+ ScopedTempDir test_dir_;
+ // A message loop that we can use as the file thread message loop.
+ MessageLoop message_loop_;
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
+};
+
+TEST_F(JsonHostConfigTest, InvalidFile) {
+ ASSERT_TRUE(test_dir_.CreateUniqueTempDir());
+ FilePath non_existent_file =
+ test_dir_.path().AppendASCII("non_existent.json");
+ scoped_refptr<JsonHostConfig> target =
+ new JsonHostConfig(non_existent_file, message_loop_proxy_.get());
+ EXPECT_FALSE(target->Read());
+}
+
+TEST_F(JsonHostConfigTest, Read) {
+ ASSERT_TRUE(test_dir_.CreateUniqueTempDir());
+ FilePath test_file = test_dir_.path().AppendASCII("read.json");
+ WriteTestFile(test_file);
+ scoped_refptr<JsonHostConfig> target =
+ new JsonHostConfig(test_file, message_loop_proxy_.get());
+ ASSERT_TRUE(target->Read());
+
+ std::string value;
+ EXPECT_TRUE(target->GetString(kXmppLoginConfigPath, &value));
+ EXPECT_EQ("test@gmail.com", value);
+ EXPECT_TRUE(target->GetString(kXmppAuthTokenConfigPath, &value));
+ EXPECT_EQ("TEST_AUTH_TOKEN", value);
+ EXPECT_TRUE(target->GetString(kHostIdConfigPath, &value));
+ EXPECT_EQ("TEST_HOST_ID", value);
+ EXPECT_TRUE(target->GetString(kHostNameConfigPath, &value));
+ EXPECT_EQ("TEST_MACHINE_NAME", value);
+ EXPECT_TRUE(target->GetString(kPublicKeyConfigPath, &value));
+ EXPECT_EQ("TEST_PUBLIC_KEY", value);
+
+ EXPECT_FALSE(target->GetString(L"non_existent_value", &value));
+}
+
+TEST_F(JsonHostConfigTest, Write) {
+ ASSERT_TRUE(test_dir_.CreateUniqueTempDir());
+
+ FilePath test_file = test_dir_.path().AppendASCII("write.json");
+ WriteTestFile(test_file);
+ scoped_refptr<JsonHostConfig> target(
+ new JsonHostConfig(test_file, message_loop_proxy_.get()));
+ ASSERT_TRUE(target->Read());
+
+ std::string new_auth_token_value = "NEW_AUTH_TOKEN";
+ scoped_refptr<TestConfigUpdater> config_updater(new TestConfigUpdater());
+ target->Update(
+ NewRunnableMethod(config_updater.get(), &TestConfigUpdater::DoUpdate,
+ target, new_auth_token_value));
+
+ message_loop_.RunAllPending();
+
+ // Now read the file again and check that the value has been written.
+ scoped_refptr<JsonHostConfig> reader(
+ new JsonHostConfig(test_file, message_loop_proxy_.get()));
+
+ ASSERT_TRUE(reader->Read());
+
+ std::string value;
+ EXPECT_TRUE(reader->GetString(kXmppLoginConfigPath, &value));
+ EXPECT_EQ("test@gmail.com", value);
+ EXPECT_TRUE(reader->GetString(kXmppAuthTokenConfigPath, &value));
+ EXPECT_EQ(new_auth_token_value, value);
+ EXPECT_TRUE(reader->GetString(kHostIdConfigPath, &value));
+ EXPECT_EQ("TEST_HOST_ID", value);
+ EXPECT_TRUE(reader->GetString(kHostNameConfigPath, &value));
+ EXPECT_EQ("TEST_MACHINE_NAME", value);
+ EXPECT_TRUE(reader->GetString(kPublicKeyConfigPath, &value));
+ EXPECT_EQ("TEST_PUBLIC_KEY", value);
+}
+
+}
diff --git a/remoting/host/session_manager.h b/remoting/host/session_manager.h
index 54aae70..9c8ad50 100644
--- a/remoting/host/session_manager.h
+++ b/remoting/host/session_manager.h
@@ -69,10 +69,10 @@ class SessionManager : public base::RefCountedThreadSafe<SessionManager> {
// Construct a SessionManager. Message loops and threads are provided.
// Ownership of Capturer and Encoder are given to this object.
SessionManager(MessageLoop* capture_loop,
- MessageLoop* encode_loop,
- MessageLoop* network_loop,
- Capturer* capturer,
- Encoder* encoder);
+ MessageLoop* encode_loop,
+ MessageLoop* network_loop,
+ Capturer* capturer,
+ Encoder* encoder);
virtual ~SessionManager();
diff --git a/remoting/host/simple_host_process.cc b/remoting/host/simple_host_process.cc
index 86890f7..5ed70e0 100644
--- a/remoting/host/simple_host_process.cc
+++ b/remoting/host/simple_host_process.cc
@@ -17,16 +17,16 @@
#include "build/build_config.h"
-#if defined(OS_POSIX)
-#include <termios.h>
-#endif // defined (OS_POSIX)
-
#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/thread.h"
#include "base/waitable_event.h"
#include "remoting/host/capturer_fake.h"
-#include "remoting/host/encoder_verbatim.h"
-#include "remoting/host/host_config.h"
#include "remoting/host/chromoting_host.h"
+#include "remoting/host/encoder_verbatim.h"
+#include "remoting/host/json_host_config.h"
#if defined(OS_WIN)
#include "remoting/host/capturer_gdi.h"
@@ -39,49 +39,20 @@
#include "remoting/host/event_executor_mac.h"
#endif
-int main(int argc, char** argv) {
- base::AtExitManager exit_manager;
+#if defined(OS_WIN)
+const std::wstring kDefaultConfigPath = L"ChromotingConfig.json";
+#else
+const std::string kDefaultConfigPath = "ChromotingConfig.json";
+#endif
- std::string username;
- std::string auth_token;
+const std::string kFakeSwitchName = "fake";
+const std::string kConfigSwitchName = "config";
- // Check the argument to see if we should use a fake capturer and encoder.
- bool fake = false;
- // True if the JID was specified on the command line.
- bool has_jid = false;
- // True if the auth token was specified on the command line.
- bool has_auth = false;
-
- for (int i = 1; i < argc; i++) {
- std::string arg = argv[i];
- if (arg == "--fake") {
- fake = true;
- } else if (arg == "--jid") {
- if (++i >= argc) {
- std::cerr << "Expected JID to follow --jid option" << std::endl;
- return 1;
- }
- has_jid = true;
- username = argv[i];
- } else if (arg == "--auth") {
- if (++i >= argc) {
- std::cerr << "Expected auth token to follow --auth option" << std::endl;
- return 1;
- }
- has_auth = true;
- auth_token = argv[i];
- }
- }
+int main(int argc, char** argv) {
+ CommandLine::Init(argc, argv);
+ const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
- // Prompt user for username and auth token.
- if (!has_jid) {
- std::cout << "JID: ";
- std::cin >> username;
- }
- if (!has_auth) {
- std::cout << "Auth Token: ";
- std::cin >> auth_token;
- }
+ base::AtExitManager exit_manager;
scoped_ptr<remoting::Capturer> capturer;
scoped_ptr<remoting::Encoder> encoder;
@@ -98,19 +69,31 @@ int main(int argc, char** argv) {
#endif
encoder.reset(new remoting::EncoderVerbatim());
+ // Check the argument to see if we should use a fake capturer and encoder.
+ bool fake = cmd_line->HasSwitch(kFakeSwitchName);
+
+ FilePath config_path(kDefaultConfigPath);
+ if (cmd_line->HasSwitch(kConfigSwitchName)) {
+ config_path = cmd_line->GetSwitchValuePath(kConfigSwitchName);
+ }
+
if (fake) {
// Inject a fake capturer.
capturer.reset(new remoting::CapturerFake());
}
- // TODO(sergeyu): Implement HostConfigStorage and use it here to load
- // settings.
- scoped_refptr<remoting::HostConfig> config(new remoting::HostConfig());
- config->set_xmpp_login(username);
- config->set_xmpp_auth_token(auth_token);
- config->set_host_id("foo");
+ base::Thread file_io_thread("FileIO");
+ file_io_thread.Start();
+
+ scoped_refptr<remoting::JsonHostConfig> config(
+ new remoting::JsonHostConfig(
+ config_path, file_io_thread.message_loop_proxy()));
+
+ if (!config->Read()) {
+ LOG(ERROR) << "Failed to read configuration file " << config_path.value();
+ return 1;
+ }
- // Construct a chromoting host with username and auth_token.
base::WaitableEvent host_done(false, false);
scoped_refptr<remoting::ChromotingHost> host =
new remoting::ChromotingHost(config,
@@ -120,5 +103,7 @@ int main(int argc, char** argv) {
&host_done);
host->Run();
host_done.Wait();
+
+ file_io_thread.Stop();
return 0;
}
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 9156951..b47053e 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -162,6 +162,7 @@
'target_name': 'chromoting_host',
'type': '<(library)',
'dependencies': [
+ '../chrome/chrome.gyp:common',
'chromoting_base',
'chromoting_jingle_glue',
],
@@ -187,7 +188,10 @@
'host/session_manager.h',
'host/heartbeat_sender.cc',
'host/heartbeat_sender.h',
+ 'host/host_config.cc',
'host/host_config.h',
+ 'host/json_host_config.cc',
+ 'host/json_host_config.h',
],
'conditions': [
['OS=="win"', {
@@ -341,6 +345,7 @@
'client/decoder_verbatim_unittest.cc',
'host/differ_unittest.cc',
'host/differ_block_unittest.cc',
+ 'host/json_host_config_unittest.cc',
'host/mock_objects.h',
'host/session_manager_unittest.cc',
# TODO(hclam): Enable VP8 in the build.
diff --git a/remoting/tools/gaia_auth.py b/remoting/tools/gaia_auth.py
new file mode 100644
index 0000000..da364e0
--- /dev/null
+++ b/remoting/tools/gaia_auth.py
@@ -0,0 +1,29 @@
+# Copyright (c) 2010 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.
+
+import getpass
+import os
+import urllib
+
+default_gaia_url = "https://www.google.com:443/accounts/ClientLogin"
+
+class GaiaAuthenticator:
+ def __init__(self, service, url = default_gaia_url):
+ self._service = service
+ self._url = url
+
+ ## Logins to gaia and returns auth token.
+ def authenticate(self, email, passwd):
+ params = urllib.urlencode({'Email': email, 'Passwd': passwd,
+ 'source': 'chromoting',
+ 'service': self._service,
+ 'PersistentCookie': 'true',
+ 'accountType': 'GOOGLE'})
+ f = urllib.urlopen(self._url, params);
+ result = f.read()
+ for line in result.splitlines():
+ if line.startswith('Auth='):
+ auth_string = line[5:]
+ return auth_string
+ raise Exception("Gaia didn't return auth token: " + result)
diff --git a/remoting/tools/gettoken.py b/remoting/tools/gettoken.py
index 31db75b..3a61927 100755
--- a/remoting/tools/gettoken.py
+++ b/remoting/tools/gettoken.py
@@ -11,7 +11,8 @@ import getpass
import os
import urllib
-url = "https://www.google.com:443/accounts/ClientLogin"
+import gaia_auth
+
auth_filename = '.chromotingAuthToken'
print "Email:",
@@ -19,32 +20,19 @@ email = raw_input()
passwd = getpass.getpass("Password: ")
-params = urllib.urlencode({'Email': email, 'Passwd': passwd,
- 'source': 'chromoting', 'service': 'chromiumsync',
- 'PersistentCookie': 'true', 'accountType': 'GOOGLE'})
-f = urllib.urlopen(url, params);
-
-auth_found = False
-for line in f:
- if line.startswith('Auth='):
- auth_string = line[5:]
-
- # Set permission mask for created file.
- os.umask(0066)
- auth_file = open(auth_filename, 'w')
- auth_file.write(email)
- auth_file.write('\n')
- auth_file.write(auth_string)
- auth_file.close()
-
- print
- print 'Auth token:'
- print
- print auth_string
- print '...saved in', auth_filename
- auth_found = True
-
-if not auth_found:
- print 'ERROR - Unable to find Auth token in output:'
- for line in f:
- print line,
+authenticator = gaia_auth.GaiaAuthenticator('chromiumsync');
+auth_token = authenticator.authenticate(email, passwd)
+
+# Set permission mask for created file.
+os.umask(0066)
+auth_file = open(auth_filename, 'w')
+auth_file.write(email)
+auth_file.write('\n')
+auth_file.write(auth_token)
+auth_file.close()
+
+print
+print 'Auth token:'
+print
+print auth_token
+print '...saved in', auth_filename
diff --git a/remoting/tools/register_host.py b/remoting/tools/register_host.py
new file mode 100755
index 0000000..bb9f473
--- /dev/null
+++ b/remoting/tools/register_host.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2010 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.
+#
+# register_host.py registers new hosts in chromoting directory. It
+# asks for username/password and then writes these settings to config file.
+
+import getpass
+import os
+import urllib
+import urllib2
+import uuid
+import sys
+
+import gaia_auth
+
+server = 'www-googleapis-test.sandbox.google.com'
+url = 'http://' + server + '/chromoting/v1/@me/hosts'
+
+settings_filename = 'ChromotingConfig.json'
+
+print "Email:",
+email = raw_input()
+password = getpass.getpass("Password: ")
+
+xapi_auth = gaia_auth.GaiaAuthenticator('xapi')
+xapi_token = xapi_auth.authenticate(email, password)
+
+host_id = str(uuid.uuid1())
+print "HostId:", host_id
+host_name = os.uname()[1]
+print "HostName:", host_name
+# TODO(sergeyu): Implement keypair generaion.
+public_key = '123123'
+jingle_id = ''
+
+#f = urllib.urlopen(url, params);
+#print params
+params = ('{"data":{' + \
+ '"host_id": "%(host_id)s",' + \
+ '"host_name": "%(host_name)s",' + \
+ '"public_key": "%(public_key)s",' + \
+ '"jingle_id": "%(jingle_id)s"}}') % \
+ {'host_id': host_id, 'host_name': host_name,
+ 'public_key': public_key, 'jingle_id': jingle_id}
+headers = {"Authorization": "GoogleLogin auth=" + xapi_token,
+ "Content-Type": "application/json" }
+request = urllib2.Request(url, params, headers)
+
+opener = urllib2.OpenerDirector()
+opener.add_handler(urllib2.HTTPDefaultErrorHandler())
+
+print
+print "Registering host with directory service..."
+try:
+ res = urllib2.urlopen(request)
+ data = res.read()
+except urllib2.HTTPError, err:
+ print >> sys.stderr, "Directory returned error:", err
+ print >> sys.stderr, err.fp.read()
+ sys.exit(1)
+
+print "Done"
+
+# Get token that the host will use to athenticate in talk network.
+authenticator = gaia_auth.GaiaAuthenticator('chromiumsync');
+auth_token = authenticator.authenticate(email, password)
+
+# Write settings file.
+os.umask(0066) # Set permission mask for created file.
+settings_file = open(settings_filename, 'w')
+settings_file.write('{\n');
+settings_file.write(' "xmpp_login" : "' + email + '",\n')
+settings_file.write(' "xmpp_auth_token" : "' + auth_token + '",\n')
+settings_file.write(' "host_id" : "' + host_id + '",\n')
+settings_file.write(' "host_name" : "' + host_name + '",\n')
+settings_file.write(' "public_key" : "' + public_key + '"\n')
+settings_file.write('}\n')
+settings_file.close()
+
+print 'Configuration saved in', settings_filename