diff options
-rw-r--r-- | remoting/DEPS | 2 | ||||
-rw-r--r-- | remoting/base/constants.cc | 2 | ||||
-rw-r--r-- | remoting/host/chromoting_host.cc | 15 | ||||
-rw-r--r-- | remoting/host/chromoting_host.h | 9 | ||||
-rw-r--r-- | remoting/host/heartbeat_sender.cc | 9 | ||||
-rw-r--r-- | remoting/host/heartbeat_sender.h | 7 | ||||
-rw-r--r-- | remoting/host/host_config.cc | 15 | ||||
-rw-r--r-- | remoting/host/host_config.h | 97 | ||||
-rw-r--r-- | remoting/host/json_host_config.cc | 64 | ||||
-rw-r--r-- | remoting/host/json_host_config.h | 59 | ||||
-rw-r--r-- | remoting/host/json_host_config_unittest.cc | 121 | ||||
-rw-r--r-- | remoting/host/session_manager.h | 8 | ||||
-rw-r--r-- | remoting/host/simple_host_process.cc | 91 | ||||
-rw-r--r-- | remoting/remoting.gyp | 5 | ||||
-rw-r--r-- | remoting/tools/gaia_auth.py | 29 | ||||
-rwxr-xr-x | remoting/tools/gettoken.py | 48 | ||||
-rwxr-xr-x | remoting/tools/register_host.py | 83 |
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 |