summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorweitaosu@chromium.org <weitaosu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-24 22:05:58 +0000
committerweitaosu@chromium.org <weitaosu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-24 22:05:58 +0000
commitd0b78c13716ef91150736b8199a7d8f70ef42e86 (patch)
tree3a8d8466f1db5c307205982315383e1b6dfc4c90
parentce29689518e756fe9999c1199058b1016209ab07 (diff)
downloadchromium_src-d0b78c13716ef91150736b8199a7d8f70ef42e86.zip
chromium_src-d0b78c13716ef91150736b8199a7d8f70ef42e86.tar.gz
chromium_src-d0b78c13716ef91150736b8199a7d8f70ef42e86.tar.bz2
Create a remoting_it2me_host_static GYP target which will be shared between the NPAPI plugin and the it2me native messaging host.
BUG=309844 Review URL: https://codereview.chromium.org/33183006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@230835 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--remoting/host/it2me/it2me_impl.cc468
-rw-r--r--remoting/host/it2me/it2me_impl.h161
-rw-r--r--remoting/host/plugin/host_script_object.cc456
-rw-r--r--remoting/host/plugin/host_script_object.h156
-rw-r--r--remoting/remoting.gyp24
5 files changed, 655 insertions, 610 deletions
diff --git a/remoting/host/it2me/it2me_impl.cc b/remoting/host/it2me/it2me_impl.cc
new file mode 100644
index 0000000..7b1b4c4
--- /dev/null
+++ b/remoting/host/it2me/it2me_impl.cc
@@ -0,0 +1,468 @@
+// Copyright 2013 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/it2me/it2me_impl.h"
+
+#include "base/bind.h"
+#include "base/strings/string_util.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/platform_thread.h"
+#include "net/socket/client_socket_factory.h"
+#include "remoting/base/auto_thread.h"
+#include "remoting/base/rsa_key_pair.h"
+#include "remoting/host/chromoting_host.h"
+#include "remoting/host/chromoting_host_context.h"
+#include "remoting/host/host_event_logger.h"
+#include "remoting/host/host_secret.h"
+#include "remoting/host/it2me_desktop_environment.h"
+#include "remoting/host/policy_hack/policy_watcher.h"
+#include "remoting/host/register_support_host_request.h"
+#include "remoting/host/session_manager_factory.h"
+#include "remoting/jingle_glue/network_settings.h"
+#include "remoting/protocol/it2me_host_authenticator_factory.h"
+
+namespace remoting {
+
+namespace {
+
+// This is used for tagging system event logs.
+const char kApplicationName[] = "chromoting";
+const int kMaxLoginAttempts = 5;
+
+} // namespace
+
+It2MeImpl::It2MeImpl(
+ scoped_ptr<ChromotingHostContext> host_context,
+ scoped_refptr<base::SingleThreadTaskRunner> plugin_task_runner,
+ base::WeakPtr<It2MeImpl::Observer> observer,
+ const XmppSignalStrategy::XmppServerConfig& xmpp_server_config,
+ const std::string& directory_bot_jid)
+ : host_context_(host_context.Pass()),
+ plugin_task_runner_(plugin_task_runner),
+ observer_(observer),
+ xmpp_server_config_(xmpp_server_config),
+ directory_bot_jid_(directory_bot_jid),
+ state_(kDisconnected),
+ failed_login_attempts_(0),
+ nat_traversal_enabled_(false),
+ policy_received_(false) {
+ DCHECK(plugin_task_runner_->BelongsToCurrentThread());
+}
+
+void It2MeImpl::Connect() {
+ if (!host_context_->ui_task_runner()->BelongsToCurrentThread()) {
+ DCHECK(plugin_task_runner_->BelongsToCurrentThread());
+ host_context_->ui_task_runner()->PostTask(
+ FROM_HERE, base::Bind(&It2MeImpl::Connect, this));
+ return;
+ }
+
+ desktop_environment_factory_.reset(new It2MeDesktopEnvironmentFactory(
+ host_context_->network_task_runner(),
+ host_context_->input_task_runner(),
+ host_context_->ui_task_runner()));
+
+ // Start monitoring configured policies.
+ policy_watcher_.reset(
+ policy_hack::PolicyWatcher::Create(host_context_->network_task_runner()));
+ policy_watcher_->StartWatching(
+ base::Bind(&It2MeImpl::OnPolicyUpdate, this));
+
+ // Switch to the network thread to start the actual connection.
+ host_context_->network_task_runner()->PostTask(
+ FROM_HERE, base::Bind(&It2MeImpl::ReadPolicyAndConnect, this));
+}
+
+void It2MeImpl::Disconnect() {
+ if (!host_context_->network_task_runner()->BelongsToCurrentThread()) {
+ DCHECK(plugin_task_runner_->BelongsToCurrentThread());
+ host_context_->network_task_runner()->PostTask(
+ FROM_HERE, base::Bind(&It2MeImpl::Disconnect, this));
+ return;
+ }
+
+ switch (state_) {
+ case kDisconnected:
+ ShutdownOnNetworkThread();
+ return;
+
+ case kStarting:
+ SetState(kDisconnecting);
+ SetState(kDisconnected);
+ ShutdownOnNetworkThread();
+ return;
+
+ case kDisconnecting:
+ return;
+
+ default:
+ SetState(kDisconnecting);
+
+ if (!host_) {
+ SetState(kDisconnected);
+ ShutdownOnNetworkThread();
+ return;
+ }
+
+ // Deleting the host destroys SignalStrategy synchronously, but
+ // SignalStrategy::Listener handlers are not allowed to destroy
+ // SignalStrategy, so post task to destroy the host later.
+ host_context_->network_task_runner()->PostTask(
+ FROM_HERE, base::Bind(&It2MeImpl::ShutdownOnNetworkThread, this));
+ return;
+ }
+}
+
+void It2MeImpl::RequestNatPolicy() {
+ if (!host_context_->network_task_runner()->BelongsToCurrentThread()) {
+ DCHECK(plugin_task_runner_->BelongsToCurrentThread());
+ host_context_->network_task_runner()->PostTask(
+ FROM_HERE, base::Bind(&It2MeImpl::RequestNatPolicy, this));
+ return;
+ }
+
+ if (policy_received_)
+ UpdateNatPolicy(nat_traversal_enabled_);
+}
+
+void It2MeImpl::ReadPolicyAndConnect() {
+ DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
+
+ SetState(kStarting);
+
+ // Only proceed to FinishConnect() if at least one policy update has been
+ // received.
+ if (policy_received_) {
+ FinishConnect();
+ } else {
+ // Otherwise, create the policy watcher, and thunk the connect.
+ pending_connect_ =
+ base::Bind(&It2MeImpl::FinishConnect, this);
+ }
+}
+
+void It2MeImpl::FinishConnect() {
+ DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
+
+ if (state_ != kStarting) {
+ // Host has been stopped while we were fetching policy.
+ return;
+ }
+
+ // Check the host domain policy.
+ if (!required_host_domain_.empty() &&
+ !EndsWith(xmpp_server_config_.username,
+ std::string("@") + required_host_domain_, false)) {
+ SetState(kInvalidDomainError);
+ return;
+ }
+
+ // Generate a key pair for the Host to use.
+ // TODO(wez): Move this to the worker thread.
+ host_key_pair_ = RsaKeyPair::Generate();
+
+ // Create XMPP connection.
+ scoped_ptr<SignalStrategy> signal_strategy(
+ new XmppSignalStrategy(net::ClientSocketFactory::GetDefaultFactory(),
+ host_context_->url_request_context_getter(),
+ xmpp_server_config_));
+
+ // Request registration of the host for support.
+ scoped_ptr<RegisterSupportHostRequest> register_request(
+ new RegisterSupportHostRequest(
+ signal_strategy.get(), host_key_pair_, directory_bot_jid_,
+ base::Bind(&It2MeImpl::OnReceivedSupportID,
+ base::Unretained(this))));
+
+ // Beyond this point nothing can fail, so save the config and request.
+ signal_strategy_ = signal_strategy.Pass();
+ register_request_ = register_request.Pass();
+
+ // If NAT traversal is off then limit port range to allow firewall pin-holing.
+ LOG(INFO) << "NAT state: " << nat_traversal_enabled_;
+ NetworkSettings network_settings(
+ nat_traversal_enabled_ ?
+ NetworkSettings::NAT_TRAVERSAL_ENABLED :
+ NetworkSettings::NAT_TRAVERSAL_DISABLED);
+ if (!nat_traversal_enabled_) {
+ network_settings.min_port = NetworkSettings::kDefaultMinPort;
+ network_settings.max_port = NetworkSettings::kDefaultMaxPort;
+ }
+
+ // Create the host.
+ host_.reset(new ChromotingHost(
+ signal_strategy_.get(),
+ desktop_environment_factory_.get(),
+ CreateHostSessionManager(network_settings,
+ host_context_->url_request_context_getter()),
+ host_context_->audio_task_runner(),
+ host_context_->input_task_runner(),
+ host_context_->video_capture_task_runner(),
+ host_context_->video_encode_task_runner(),
+ host_context_->network_task_runner(),
+ host_context_->ui_task_runner()));
+ host_->AddStatusObserver(this);
+ log_to_server_.reset(
+ new LogToServer(host_->AsWeakPtr(), ServerLogEntry::IT2ME,
+ signal_strategy_.get(), directory_bot_jid_));
+
+ // Disable audio by default.
+ // TODO(sergeyu): Add UI to enable it.
+ scoped_ptr<protocol::CandidateSessionConfig> protocol_config =
+ protocol::CandidateSessionConfig::CreateDefault();
+ protocol::CandidateSessionConfig::DisableAudioChannel(protocol_config.get());
+
+ // VP9 encode is not yet supported.
+ protocol::CandidateSessionConfig::DisableVideoCodec(
+ protocol_config.get(), protocol::ChannelConfig::CODEC_VP9);
+
+ host_->set_protocol_config(protocol_config.Pass());
+
+ // Create event logger.
+ host_event_logger_ =
+ HostEventLogger::Create(host_->AsWeakPtr(), kApplicationName);
+
+ // Connect signaling and start the host.
+ signal_strategy_->Connect();
+ host_->Start(xmpp_server_config_.username);
+
+ SetState(kRequestedAccessCode);
+ return;
+}
+
+void It2MeImpl::ShutdownOnNetworkThread() {
+ DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
+ DCHECK(state_ == kDisconnecting || state_ == kDisconnected);
+
+ if (state_ == kDisconnecting) {
+ host_event_logger_.reset();
+ host_->RemoveStatusObserver(this);
+ host_.reset();
+
+ register_request_.reset();
+ log_to_server_.reset();
+ signal_strategy_.reset();
+ SetState(kDisconnected);
+ }
+
+ host_context_->ui_task_runner()->PostTask(
+ FROM_HERE, base::Bind(&It2MeImpl::ShutdownOnUiThread, this));
+}
+
+void It2MeImpl::ShutdownOnUiThread() {
+ DCHECK(host_context_->ui_task_runner()->BelongsToCurrentThread());
+
+ // Destroy the DesktopEnvironmentFactory, to free thread references.
+ desktop_environment_factory_.reset();
+
+ // Stop listening for policy updates.
+ if (policy_watcher_.get()) {
+ base::WaitableEvent policy_watcher_stopped_(true, false);
+ policy_watcher_->StopWatching(&policy_watcher_stopped_);
+ policy_watcher_stopped_.Wait();
+ policy_watcher_.reset();
+ }
+}
+
+void It2MeImpl::OnAccessDenied(const std::string& jid) {
+ DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
+
+ ++failed_login_attempts_;
+ if (failed_login_attempts_ == kMaxLoginAttempts) {
+ Disconnect();
+ }
+}
+
+void It2MeImpl::OnClientAuthenticated(
+ const std::string& jid) {
+ DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
+
+ if (state_ == kDisconnecting) {
+ // Ignore the new connection if we are disconnecting.
+ return;
+ }
+ if (state_ == kConnected) {
+ // If we already connected another client then one of the connections may be
+ // an attacker, so both are suspect and we have to reject the second
+ // connection and shutdown the host.
+ host_->RejectAuthenticatingClient();
+ Disconnect();
+ return;
+ }
+
+ std::string client_username = jid;
+ size_t pos = client_username.find('/');
+ if (pos != std::string::npos)
+ client_username.replace(pos, std::string::npos, "");
+
+ LOG(INFO) << "Client " << client_username << " connected.";
+
+ // Pass the client user name to the script object before changing state.
+ plugin_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&It2MeImpl::Observer::OnClientAuthenticated,
+ observer_, client_username));
+
+ SetState(kConnected);
+}
+
+void It2MeImpl::OnClientDisconnected(
+ const std::string& jid) {
+ DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
+
+ Disconnect();
+}
+
+void It2MeImpl::OnPolicyUpdate(
+ scoped_ptr<base::DictionaryValue> policies) {
+ DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
+
+ bool nat_policy;
+ if (policies->GetBoolean(policy_hack::PolicyWatcher::kNatPolicyName,
+ &nat_policy)) {
+ UpdateNatPolicy(nat_policy);
+ }
+ std::string host_domain;
+ if (policies->GetString(policy_hack::PolicyWatcher::kHostDomainPolicyName,
+ &host_domain)) {
+ UpdateHostDomainPolicy(host_domain);
+ }
+
+ policy_received_ = true;
+
+ if (!pending_connect_.is_null()) {
+ pending_connect_.Run();
+ pending_connect_.Reset();
+ }
+}
+
+void It2MeImpl::UpdateNatPolicy(
+ bool nat_traversal_enabled) {
+ DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
+
+ VLOG(2) << "UpdateNatPolicy: " << nat_traversal_enabled;
+
+ // When transitioning from enabled to disabled, force disconnect any
+ // existing session.
+ if (nat_traversal_enabled_ && !nat_traversal_enabled && IsConnected()) {
+ Disconnect();
+ }
+
+ nat_traversal_enabled_ = nat_traversal_enabled;
+
+ // Notify the web-app of the policy setting.
+ plugin_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&It2MeImpl::Observer::OnNatPolicyChanged,
+ observer_, nat_traversal_enabled_));
+}
+
+void It2MeImpl::UpdateHostDomainPolicy(
+ const std::string& host_domain) {
+ DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
+
+ VLOG(2) << "UpdateHostDomainPolicy: " << host_domain;
+
+ // When setting a host domain policy, force disconnect any existing session.
+ if (!host_domain.empty() && IsConnected()) {
+ Disconnect();
+ }
+
+ required_host_domain_ = host_domain;
+}
+
+It2MeImpl::~It2MeImpl() {
+ // Check that resources that need to be torn down on the UI thread are gone.
+ DCHECK(!desktop_environment_factory_.get());
+ DCHECK(!policy_watcher_.get());
+}
+
+void It2MeImpl::SetState(It2MeHostState state) {
+ DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
+
+ switch (state_) {
+ case kDisconnected:
+ DCHECK(state == kStarting ||
+ state == kError) << state;
+ break;
+ case kStarting:
+ DCHECK(state == kRequestedAccessCode ||
+ state == kDisconnecting ||
+ state == kError ||
+ state == kInvalidDomainError) << state;
+ break;
+ case kRequestedAccessCode:
+ DCHECK(state == kReceivedAccessCode ||
+ state == kDisconnecting ||
+ state == kError) << state;
+ break;
+ case kReceivedAccessCode:
+ DCHECK(state == kConnected ||
+ state == kDisconnecting ||
+ state == kError) << state;
+ break;
+ case kConnected:
+ DCHECK(state == kDisconnecting ||
+ state == kDisconnected ||
+ state == kError) << state;
+ break;
+ case kDisconnecting:
+ DCHECK(state == kDisconnected) << state;
+ break;
+ case kError:
+ DCHECK(state == kDisconnecting) << state;
+ break;
+ case kInvalidDomainError:
+ DCHECK(state == kDisconnecting) << state;
+ break;
+ };
+
+ state_ = state;
+
+ // Post a state-change notification to the web-app.
+ plugin_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&It2MeImpl::Observer::OnStateChanged,
+ observer_, state));
+}
+
+bool It2MeImpl::IsConnected() const {
+ return state_ == kRequestedAccessCode || state_ == kReceivedAccessCode ||
+ state_ == kConnected;
+}
+
+void It2MeImpl::OnReceivedSupportID(
+ bool success,
+ const std::string& support_id,
+ const base::TimeDelta& lifetime) {
+ DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
+
+ if (!success) {
+ SetState(kError);
+ Disconnect();
+ return;
+ }
+
+ std::string host_secret = GenerateSupportHostSecret();
+ std::string access_code = support_id + host_secret;
+
+ std::string local_certificate = host_key_pair_->GenerateCertificate();
+ if (local_certificate.empty()) {
+ LOG(ERROR) << "Failed to generate host certificate.";
+ SetState(kError);
+ Disconnect();
+ return;
+ }
+
+ scoped_ptr<protocol::AuthenticatorFactory> factory(
+ new protocol::It2MeHostAuthenticatorFactory(
+ local_certificate, host_key_pair_, access_code));
+ host_->SetAuthenticatorFactory(factory.Pass());
+
+ // Pass the Access Code to the script object before changing state.
+ plugin_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&It2MeImpl::Observer::OnStoreAccessCode,
+ observer_, access_code, lifetime));
+
+ SetState(kReceivedAccessCode);
+}
+
+} // namespace remoting
diff --git a/remoting/host/it2me/it2me_impl.h b/remoting/host/it2me/it2me_impl.h
new file mode 100644
index 0000000..f31709b
--- /dev/null
+++ b/remoting/host/it2me/it2me_impl.h
@@ -0,0 +1,161 @@
+// Copyright 2013 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_IT2ME__IT2ME_IMPL_H_
+#define REMOTING_HOST_IT2ME__IT2ME_IMPL_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "remoting/host/log_to_server.h"
+#include "remoting/jingle_glue/xmpp_signal_strategy.h"
+
+namespace remoting {
+
+class RegisterSupportHostRequest;
+class HostNPScriptObject;
+class DesktopEnvironmentFactory;
+class HostEventLogger;
+class ChromotingHost;
+class ChromotingHostContext;
+
+namespace policy_hack {
+
+class PolicyWatcher;
+
+} // namespace policy_hack
+
+// These state values are duplicated in host_session.js. Remember to update
+// both copies when making changes.
+enum It2MeHostState {
+ kDisconnected,
+ kStarting,
+ kRequestedAccessCode,
+ kReceivedAccessCode,
+ kConnected,
+ kDisconnecting,
+ kError,
+ kInvalidDomainError
+};
+
+// Internal implementation of the plugin's It2Me host function.
+class It2MeImpl
+ : public base::RefCountedThreadSafe<It2MeImpl>,
+ public HostStatusObserver {
+ public:
+
+ class Observer {
+ public:
+ virtual void OnClientAuthenticated(const std::string& client_username) = 0;
+ virtual void OnStoreAccessCode(const std::string& access_code,
+ base::TimeDelta access_code_lifetime) = 0;
+ virtual void OnNatPolicyChanged(bool nat_traversal_enabled) = 0;
+ virtual void OnStateChanged(It2MeHostState state) = 0;
+ };
+
+ It2MeImpl(
+ scoped_ptr<ChromotingHostContext> context,
+ scoped_refptr<base::SingleThreadTaskRunner> plugin_task_runner,
+ base::WeakPtr<It2MeImpl::Observer> observer,
+ const XmppSignalStrategy::XmppServerConfig& xmpp_server_config,
+ const std::string& directory_bot_jid);
+
+ // Methods called by the script object, from the plugin thread.
+
+ // Creates It2Me host structures and starts the host.
+ void Connect();
+
+ // Disconnects the host, ready for tear-down.
+ // Also called internally, from the network thread.
+ void Disconnect();
+
+ // Request a NAT policy notification.
+ void RequestNatPolicy();
+
+ // remoting::HostStatusObserver implementation.
+ virtual void OnAccessDenied(const std::string& jid) OVERRIDE;
+ virtual void OnClientAuthenticated(const std::string& jid) OVERRIDE;
+ virtual void OnClientDisconnected(const std::string& jid) OVERRIDE;
+
+ private:
+ friend class base::RefCountedThreadSafe<It2MeImpl>;
+
+ virtual ~It2MeImpl();
+
+ // Updates state of the host. Can be called only on the network thread.
+ void SetState(It2MeHostState state);
+
+ // Returns true if the host is connected.
+ bool IsConnected() const;
+
+ // Called by Connect() to check for policies and start connection process.
+ void ReadPolicyAndConnect();
+
+ // Called by ReadPolicyAndConnect once policies have been read.
+ void FinishConnect();
+
+ // Called when the support host registration completes.
+ void OnReceivedSupportID(bool success,
+ const std::string& support_id,
+ const base::TimeDelta& lifetime);
+
+ // Shuts down |host_| on the network thread and posts ShutdownOnUiThread()
+ // to shut down UI thread resources.
+ void ShutdownOnNetworkThread();
+
+ // Shuts down |desktop_environment_factory_| and |policy_watcher_| on
+ // the UI thread.
+ void ShutdownOnUiThread();
+
+ // Called when initial policies are read, and when they change.
+ void OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies);
+
+ // Handlers for NAT traversal and host domain policies.
+ void UpdateNatPolicy(bool nat_traversal_enabled);
+ void UpdateHostDomainPolicy(const std::string& host_domain);
+
+ // Caller supplied fields.
+ scoped_ptr<ChromotingHostContext> host_context_;
+ scoped_refptr<base::SingleThreadTaskRunner> plugin_task_runner_;
+ base::WeakPtr<It2MeImpl::Observer> observer_;
+ XmppSignalStrategy::XmppServerConfig xmpp_server_config_;
+ std::string directory_bot_jid_;
+
+ It2MeHostState state_;
+
+ scoped_refptr<RsaKeyPair> host_key_pair_;
+ scoped_ptr<SignalStrategy> signal_strategy_;
+ scoped_ptr<RegisterSupportHostRequest> register_request_;
+ scoped_ptr<LogToServer> log_to_server_;
+ scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_;
+ scoped_ptr<HostEventLogger> host_event_logger_;
+
+ scoped_ptr<ChromotingHost> host_;
+ int failed_login_attempts_;
+
+ scoped_ptr<policy_hack::PolicyWatcher> policy_watcher_;
+
+ // Host the current nat traversal policy setting.
+ bool nat_traversal_enabled_;
+
+ // The host domain policy setting.
+ std::string required_host_domain_;
+
+ // Indicates whether or not a policy has ever been read. This is to ensure
+ // that on startup, we do not accidentally start a connection before we have
+ // queried our policy restrictions.
+ bool policy_received_;
+
+ // On startup, it is possible to have Connect() called before the policy read
+ // is completed. Rather than just failing, we thunk the connection call so
+ // it can be executed after at least one successful policy read. This
+ // variable contains the thunk if it is necessary.
+ base::Closure pending_connect_;
+
+ DISALLOW_COPY_AND_ASSIGN(It2MeImpl);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_HOST_IT2ME__IT2ME_IMPL_H_
diff --git a/remoting/host/plugin/host_script_object.cc b/remoting/host/plugin/host_script_object.cc
index 1b173db..66d228c 100644
--- a/remoting/host/plugin/host_script_object.cc
+++ b/remoting/host/plugin/host_script_object.cc
@@ -7,46 +7,29 @@
#include "base/bind.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/threading/platform_thread.h"
-#include "base/values.h"
-#include "net/base/net_util.h"
-#include "net/socket/client_socket_factory.h"
#include "remoting/base/auth_token_util.h"
#include "remoting/base/auto_thread.h"
#include "remoting/base/resources.h"
#include "remoting/base/rsa_key_pair.h"
-#include "remoting/host/chromoting_host.h"
#include "remoting/host/chromoting_host_context.h"
#include "remoting/host/host_config.h"
-#include "remoting/host/host_event_logger.h"
-#include "remoting/host/host_secret.h"
-#include "remoting/host/host_status_observer.h"
-#include "remoting/host/it2me_desktop_environment.h"
#include "remoting/host/pairing_registry_delegate.h"
#include "remoting/host/pin_hash.h"
#include "remoting/host/plugin/host_log_handler.h"
#include "remoting/host/policy_hack/policy_watcher.h"
-#include "remoting/host/register_support_host_request.h"
#include "remoting/host/service_urls.h"
-#include "remoting/host/session_manager_factory.h"
-#include "remoting/jingle_glue/network_settings.h"
-#include "remoting/jingle_glue/xmpp_signal_strategy.h"
-#include "remoting/protocol/it2me_host_authenticator_factory.h"
+#include "third_party/npapi/bindings/npapi.h"
+#include "third_party/npapi/bindings/npfunctions.h"
#include "third_party/npapi/bindings/npruntime.h"
namespace remoting {
namespace {
-// This is used for tagging system event logs.
-const char kApplicationName[] = "chromoting";
-
const char* kAttrNameAccessCode = "accessCode";
const char* kAttrNameAccessCodeLifetime = "accessCodeLifetime";
const char* kAttrNameClient = "client";
@@ -86,446 +69,11 @@ const char* kAttrNameDisconnecting = "DISCONNECTING";
const char* kAttrNameError = "ERROR";
const char* kAttrNameInvalidDomainError = "INVALID_DOMAIN_ERROR";
-const int kMaxLoginAttempts = 5;
-
// Space separated list of features supported in addition to the base protocol.
const char* kSupportedFeatures = "pairingRegistry";
} // namespace
-It2MeImpl::It2MeImpl(
- scoped_ptr<ChromotingHostContext> host_context,
- scoped_refptr<base::SingleThreadTaskRunner> plugin_task_runner,
- base::WeakPtr<It2MeImpl::Observer> observer,
- const XmppSignalStrategy::XmppServerConfig& xmpp_server_config,
- const std::string& directory_bot_jid)
- : host_context_(host_context.Pass()),
- plugin_task_runner_(plugin_task_runner),
- observer_(observer),
- xmpp_server_config_(xmpp_server_config),
- directory_bot_jid_(directory_bot_jid),
- state_(kDisconnected),
- failed_login_attempts_(0),
- nat_traversal_enabled_(false),
- policy_received_(false) {
- DCHECK(plugin_task_runner_->BelongsToCurrentThread());
-}
-
-void It2MeImpl::Connect() {
- if (!host_context_->ui_task_runner()->BelongsToCurrentThread()) {
- DCHECK(plugin_task_runner_->BelongsToCurrentThread());
- host_context_->ui_task_runner()->PostTask(
- FROM_HERE, base::Bind(&It2MeImpl::Connect, this));
- return;
- }
-
- desktop_environment_factory_.reset(new It2MeDesktopEnvironmentFactory(
- host_context_->network_task_runner(),
- host_context_->input_task_runner(),
- host_context_->ui_task_runner()));
-
- // Start monitoring configured policies.
- policy_watcher_.reset(
- policy_hack::PolicyWatcher::Create(host_context_->network_task_runner()));
- policy_watcher_->StartWatching(
- base::Bind(&It2MeImpl::OnPolicyUpdate, this));
-
- // Switch to the network thread to start the actual connection.
- host_context_->network_task_runner()->PostTask(
- FROM_HERE, base::Bind(&It2MeImpl::ReadPolicyAndConnect, this));
-}
-
-void It2MeImpl::Disconnect() {
- if (!host_context_->network_task_runner()->BelongsToCurrentThread()) {
- DCHECK(plugin_task_runner_->BelongsToCurrentThread());
- host_context_->network_task_runner()->PostTask(
- FROM_HERE, base::Bind(&It2MeImpl::Disconnect, this));
- return;
- }
-
- switch (state_) {
- case kDisconnected:
- ShutdownOnNetworkThread();
- return;
-
- case kStarting:
- SetState(kDisconnecting);
- SetState(kDisconnected);
- ShutdownOnNetworkThread();
- return;
-
- case kDisconnecting:
- return;
-
- default:
- SetState(kDisconnecting);
-
- if (!host_) {
- SetState(kDisconnected);
- ShutdownOnNetworkThread();
- return;
- }
-
- // Deleting the host destroys SignalStrategy synchronously, but
- // SignalStrategy::Listener handlers are not allowed to destroy
- // SignalStrategy, so post task to destroy the host later.
- host_context_->network_task_runner()->PostTask(
- FROM_HERE, base::Bind(&It2MeImpl::ShutdownOnNetworkThread, this));
- return;
- }
-}
-
-void It2MeImpl::RequestNatPolicy() {
- if (!host_context_->network_task_runner()->BelongsToCurrentThread()) {
- DCHECK(plugin_task_runner_->BelongsToCurrentThread());
- host_context_->network_task_runner()->PostTask(
- FROM_HERE, base::Bind(&It2MeImpl::RequestNatPolicy, this));
- return;
- }
-
- if (policy_received_)
- UpdateNatPolicy(nat_traversal_enabled_);
-}
-
-void It2MeImpl::ReadPolicyAndConnect() {
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
-
- SetState(kStarting);
-
- // Only proceed to FinishConnect() if at least one policy update has been
- // received.
- if (policy_received_) {
- FinishConnect();
- } else {
- // Otherwise, create the policy watcher, and thunk the connect.
- pending_connect_ =
- base::Bind(&It2MeImpl::FinishConnect, this);
- }
-}
-
-void It2MeImpl::FinishConnect() {
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
-
- if (state_ != kStarting) {
- // Host has been stopped while we were fetching policy.
- return;
- }
-
- // Check the host domain policy.
- if (!required_host_domain_.empty() &&
- !EndsWith(xmpp_server_config_.username,
- std::string("@") + required_host_domain_, false)) {
- SetState(kInvalidDomainError);
- return;
- }
-
- // Generate a key pair for the Host to use.
- // TODO(wez): Move this to the worker thread.
- host_key_pair_ = RsaKeyPair::Generate();
-
- // Create XMPP connection.
- scoped_ptr<SignalStrategy> signal_strategy(
- new XmppSignalStrategy(net::ClientSocketFactory::GetDefaultFactory(),
- host_context_->url_request_context_getter(),
- xmpp_server_config_));
-
- // Request registration of the host for support.
- scoped_ptr<RegisterSupportHostRequest> register_request(
- new RegisterSupportHostRequest(
- signal_strategy.get(), host_key_pair_, directory_bot_jid_,
- base::Bind(&It2MeImpl::OnReceivedSupportID,
- base::Unretained(this))));
-
- // Beyond this point nothing can fail, so save the config and request.
- signal_strategy_ = signal_strategy.Pass();
- register_request_ = register_request.Pass();
-
- // If NAT traversal is off then limit port range to allow firewall pin-holing.
- LOG(INFO) << "NAT state: " << nat_traversal_enabled_;
- NetworkSettings network_settings(
- nat_traversal_enabled_ ?
- NetworkSettings::NAT_TRAVERSAL_ENABLED :
- NetworkSettings::NAT_TRAVERSAL_DISABLED);
- if (!nat_traversal_enabled_) {
- network_settings.min_port = NetworkSettings::kDefaultMinPort;
- network_settings.max_port = NetworkSettings::kDefaultMaxPort;
- }
-
- // Create the host.
- host_.reset(new ChromotingHost(
- signal_strategy_.get(),
- desktop_environment_factory_.get(),
- CreateHostSessionManager(network_settings,
- host_context_->url_request_context_getter()),
- host_context_->audio_task_runner(),
- host_context_->input_task_runner(),
- host_context_->video_capture_task_runner(),
- host_context_->video_encode_task_runner(),
- host_context_->network_task_runner(),
- host_context_->ui_task_runner()));
- host_->AddStatusObserver(this);
- log_to_server_.reset(
- new LogToServer(host_->AsWeakPtr(), ServerLogEntry::IT2ME,
- signal_strategy_.get(), directory_bot_jid_));
-
- // Disable audio by default.
- // TODO(sergeyu): Add UI to enable it.
- scoped_ptr<protocol::CandidateSessionConfig> protocol_config =
- protocol::CandidateSessionConfig::CreateDefault();
- protocol::CandidateSessionConfig::DisableAudioChannel(protocol_config.get());
-
- // VP9 encode is not yet supported.
- protocol::CandidateSessionConfig::DisableVideoCodec(
- protocol_config.get(), protocol::ChannelConfig::CODEC_VP9);
-
- host_->set_protocol_config(protocol_config.Pass());
-
- // Create event logger.
- host_event_logger_ =
- HostEventLogger::Create(host_->AsWeakPtr(), kApplicationName);
-
- // Connect signaling and start the host.
- signal_strategy_->Connect();
- host_->Start(xmpp_server_config_.username);
-
- SetState(kRequestedAccessCode);
- return;
-}
-
-void It2MeImpl::ShutdownOnNetworkThread() {
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
- DCHECK(state_ == kDisconnecting || state_ == kDisconnected);
-
- if (state_ == kDisconnecting) {
- host_event_logger_.reset();
- host_->RemoveStatusObserver(this);
- host_.reset();
-
- register_request_.reset();
- log_to_server_.reset();
- signal_strategy_.reset();
- SetState(kDisconnected);
- }
-
- host_context_->ui_task_runner()->PostTask(
- FROM_HERE, base::Bind(&It2MeImpl::ShutdownOnUiThread, this));
-}
-
-void It2MeImpl::ShutdownOnUiThread() {
- DCHECK(host_context_->ui_task_runner()->BelongsToCurrentThread());
-
- // Destroy the DesktopEnvironmentFactory, to free thread references.
- desktop_environment_factory_.reset();
-
- // Stop listening for policy updates.
- if (policy_watcher_.get()) {
- base::WaitableEvent policy_watcher_stopped_(true, false);
- policy_watcher_->StopWatching(&policy_watcher_stopped_);
- policy_watcher_stopped_.Wait();
- policy_watcher_.reset();
- }
-}
-
-void It2MeImpl::OnAccessDenied(const std::string& jid) {
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
-
- ++failed_login_attempts_;
- if (failed_login_attempts_ == kMaxLoginAttempts) {
- Disconnect();
- }
-}
-
-void It2MeImpl::OnClientAuthenticated(
- const std::string& jid) {
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
-
- if (state_ == kDisconnecting) {
- // Ignore the new connection if we are disconnecting.
- return;
- }
- if (state_ == kConnected) {
- // If we already connected another client then one of the connections may be
- // an attacker, so both are suspect and we have to reject the second
- // connection and shutdown the host.
- host_->RejectAuthenticatingClient();
- Disconnect();
- return;
- }
-
- std::string client_username = jid;
- size_t pos = client_username.find('/');
- if (pos != std::string::npos)
- client_username.replace(pos, std::string::npos, "");
-
- LOG(INFO) << "Client " << client_username << " connected.";
-
- // Pass the client user name to the script object before changing state.
- plugin_task_runner_->PostTask(
- FROM_HERE, base::Bind(&It2MeImpl::Observer::OnClientAuthenticated,
- observer_, client_username));
-
- SetState(kConnected);
-}
-
-void It2MeImpl::OnClientDisconnected(
- const std::string& jid) {
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
-
- Disconnect();
-}
-
-void It2MeImpl::OnPolicyUpdate(
- scoped_ptr<base::DictionaryValue> policies) {
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
-
- bool nat_policy;
- if (policies->GetBoolean(policy_hack::PolicyWatcher::kNatPolicyName,
- &nat_policy)) {
- UpdateNatPolicy(nat_policy);
- }
- std::string host_domain;
- if (policies->GetString(policy_hack::PolicyWatcher::kHostDomainPolicyName,
- &host_domain)) {
- UpdateHostDomainPolicy(host_domain);
- }
-
- policy_received_ = true;
-
- if (!pending_connect_.is_null()) {
- pending_connect_.Run();
- pending_connect_.Reset();
- }
-}
-
-void It2MeImpl::UpdateNatPolicy(
- bool nat_traversal_enabled) {
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
-
- VLOG(2) << "UpdateNatPolicy: " << nat_traversal_enabled;
-
- // When transitioning from enabled to disabled, force disconnect any
- // existing session.
- if (nat_traversal_enabled_ && !nat_traversal_enabled && IsConnected()) {
- Disconnect();
- }
-
- nat_traversal_enabled_ = nat_traversal_enabled;
-
- // Notify the web-app of the policy setting.
- plugin_task_runner_->PostTask(
- FROM_HERE, base::Bind(&It2MeImpl::Observer::OnNatPolicyChanged,
- observer_, nat_traversal_enabled_));
-}
-
-void It2MeImpl::UpdateHostDomainPolicy(
- const std::string& host_domain) {
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
-
- VLOG(2) << "UpdateHostDomainPolicy: " << host_domain;
-
- // When setting a host domain policy, force disconnect any existing session.
- if (!host_domain.empty() && IsConnected()) {
- Disconnect();
- }
-
- required_host_domain_ = host_domain;
-}
-
-It2MeImpl::~It2MeImpl() {
- // Check that resources that need to be torn down on the UI thread are gone.
- DCHECK(!desktop_environment_factory_.get());
- DCHECK(!policy_watcher_.get());
-}
-
-void It2MeImpl::SetState(It2MeHostState state) {
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
-
- switch (state_) {
- case kDisconnected:
- DCHECK(state == kStarting ||
- state == kError) << state;
- break;
- case kStarting:
- DCHECK(state == kRequestedAccessCode ||
- state == kDisconnecting ||
- state == kError ||
- state == kInvalidDomainError) << state;
- break;
- case kRequestedAccessCode:
- DCHECK(state == kReceivedAccessCode ||
- state == kDisconnecting ||
- state == kError) << state;
- break;
- case kReceivedAccessCode:
- DCHECK(state == kConnected ||
- state == kDisconnecting ||
- state == kError) << state;
- break;
- case kConnected:
- DCHECK(state == kDisconnecting ||
- state == kDisconnected ||
- state == kError) << state;
- break;
- case kDisconnecting:
- DCHECK(state == kDisconnected) << state;
- break;
- case kError:
- DCHECK(state == kDisconnecting) << state;
- break;
- case kInvalidDomainError:
- DCHECK(state == kDisconnecting) << state;
- break;
- };
-
- state_ = state;
-
- // Post a state-change notification to the web-app.
- plugin_task_runner_->PostTask(
- FROM_HERE, base::Bind(&It2MeImpl::Observer::OnStateChanged,
- observer_, state));
-}
-
-bool It2MeImpl::IsConnected() const {
- return state_ == kRequestedAccessCode || state_ == kReceivedAccessCode ||
- state_ == kConnected;
-}
-
-void It2MeImpl::OnReceivedSupportID(
- bool success,
- const std::string& support_id,
- const base::TimeDelta& lifetime) {
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
-
- if (!success) {
- SetState(kError);
- Disconnect();
- return;
- }
-
- std::string host_secret = GenerateSupportHostSecret();
- std::string access_code = support_id + host_secret;
-
- std::string local_certificate = host_key_pair_->GenerateCertificate();
- if (local_certificate.empty()) {
- LOG(ERROR) << "Failed to generate host certificate.";
- SetState(kError);
- Disconnect();
- return;
- }
-
- scoped_ptr<protocol::AuthenticatorFactory> factory(
- new protocol::It2MeHostAuthenticatorFactory(
- local_certificate, host_key_pair_, access_code));
- host_->SetAuthenticatorFactory(factory.Pass());
-
- // Pass the Access Code to the script object before changing state.
- plugin_task_runner_->PostTask(
- FROM_HERE, base::Bind(&It2MeImpl::Observer::OnStoreAccessCode,
- observer_, access_code, lifetime));
-
- SetState(kReceivedAccessCode);
-}
-
HostNPScriptObject::HostNPScriptObject(
NPP plugin,
NPObject* parent,
diff --git a/remoting/host/plugin/host_script_object.h b/remoting/host/plugin/host_script_object.h
index afcc983..74abcd9 100644
--- a/remoting/host/plugin/host_script_object.h
+++ b/remoting/host/plugin/host_script_object.h
@@ -8,173 +8,19 @@
#include <string>
#include <vector>
-#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/strings/string16.h"
-#include "base/synchronization/cancellation_flag.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
#include "base/thread_task_runner_handle.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread.h"
#include "base/time/time.h"
#include "remoting/base/auto_thread_task_runner.h"
-#include "remoting/host/chromoting_host_context.h"
-#include "remoting/host/log_to_server.h"
+#include "remoting/host/it2me/it2me_impl.h"
#include "remoting/host/plugin/host_plugin_utils.h"
#include "remoting/host/setup/daemon_controller.h"
#include "remoting/jingle_glue/xmpp_signal_strategy.h"
#include "remoting/protocol/pairing_registry.h"
-#include "third_party/npapi/bindings/npapi.h"
-#include "third_party/npapi/bindings/npfunctions.h"
-#include "third_party/npapi/bindings/npruntime.h"
namespace remoting {
-class RegisterSupportHostRequest;
-class HostNPScriptObject;
-class DesktopEnvironmentFactory;
-class HostEventLogger;
-class ChromotingHost;
-
-namespace policy_hack {
-
-class PolicyWatcher;
-
-} // namespace policy_hack
-
-// These state values are duplicated in host_session.js. Remember to update
-// both copies when making changes.
-enum It2MeHostState {
- kDisconnected,
- kStarting,
- kRequestedAccessCode,
- kReceivedAccessCode,
- kConnected,
- kDisconnecting,
- kError,
- kInvalidDomainError
-};
-
-// Internal implementation of the plugin's It2Me host function.
-class It2MeImpl
- : public base::RefCountedThreadSafe<It2MeImpl>,
- public HostStatusObserver {
- public:
-
- class Observer {
- public:
- virtual void OnClientAuthenticated(const std::string& client_username) = 0;
- virtual void OnStoreAccessCode(const std::string& access_code,
- base::TimeDelta access_code_lifetime) = 0;
- virtual void OnNatPolicyChanged(bool nat_traversal_enabled) = 0;
- virtual void OnStateChanged(It2MeHostState state) = 0;
- };
-
- It2MeImpl(
- scoped_ptr<ChromotingHostContext> context,
- scoped_refptr<base::SingleThreadTaskRunner> plugin_task_runner,
- base::WeakPtr<It2MeImpl::Observer> observer,
- const XmppSignalStrategy::XmppServerConfig& xmpp_server_config,
- const std::string& directory_bot_jid);
-
- // Methods called by the script object, from the plugin thread.
-
- // Creates It2Me host structures and starts the host.
- void Connect();
-
- // Disconnects the host, ready for tear-down.
- // Also called internally, from the network thread.
- void Disconnect();
-
- // Request a NAT policy notification.
- void RequestNatPolicy();
-
- // remoting::HostStatusObserver implementation.
- virtual void OnAccessDenied(const std::string& jid) OVERRIDE;
- virtual void OnClientAuthenticated(const std::string& jid) OVERRIDE;
- virtual void OnClientDisconnected(const std::string& jid) OVERRIDE;
-
- private:
- friend class base::RefCountedThreadSafe<It2MeImpl>;
-
- virtual ~It2MeImpl();
-
- // Updates state of the host. Can be called only on the network thread.
- void SetState(It2MeHostState state);
-
- // Returns true if the host is connected.
- bool IsConnected() const;
-
- // Called by Connect() to check for policies and start connection process.
- void ReadPolicyAndConnect();
-
- // Called by ReadPolicyAndConnect once policies have been read.
- void FinishConnect();
-
- // Called when the support host registration completes.
- void OnReceivedSupportID(bool success,
- const std::string& support_id,
- const base::TimeDelta& lifetime);
-
- // Shuts down |host_| on the network thread and posts ShutdownOnUiThread()
- // to shut down UI thread resources.
- void ShutdownOnNetworkThread();
-
- // Shuts down |desktop_environment_factory_| and |policy_watcher_| on
- // the UI thread.
- void ShutdownOnUiThread();
-
- // Called when initial policies are read, and when they change.
- void OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies);
-
- // Handlers for NAT traversal and host domain policies.
- void UpdateNatPolicy(bool nat_traversal_enabled);
- void UpdateHostDomainPolicy(const std::string& host_domain);
-
- // Caller supplied fields.
- scoped_ptr<ChromotingHostContext> host_context_;
- scoped_refptr<base::SingleThreadTaskRunner> plugin_task_runner_;
- base::WeakPtr<It2MeImpl::Observer> observer_;
- XmppSignalStrategy::XmppServerConfig xmpp_server_config_;
- std::string directory_bot_jid_;
-
- It2MeHostState state_;
-
- scoped_refptr<RsaKeyPair> host_key_pair_;
- scoped_ptr<SignalStrategy> signal_strategy_;
- scoped_ptr<RegisterSupportHostRequest> register_request_;
- scoped_ptr<LogToServer> log_to_server_;
- scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_;
- scoped_ptr<HostEventLogger> host_event_logger_;
-
- scoped_ptr<ChromotingHost> host_;
- int failed_login_attempts_;
-
- scoped_ptr<policy_hack::PolicyWatcher> policy_watcher_;
-
- // Host the current nat traversal policy setting.
- bool nat_traversal_enabled_;
-
- // The host domain policy setting.
- std::string required_host_domain_;
-
- // Indicates whether or not a policy has ever been read. This is to ensure
- // that on startup, we do not accidentally start a connection before we have
- // queried our policy restrictions.
- bool policy_received_;
-
- // On startup, it is possible to have Connect() called before the policy read
- // is completed. Rather than just failing, we thunk the connection call so
- // it can be executed after at least one successful policy read. This
- // variable contains the thunk if it is necessary.
- base::Closure pending_connect_;
-
- DISALLOW_COPY_AND_ASSIGN(It2MeImpl);
-};
-
// NPAPI plugin implementation for remoting host script object.
// HostNPScriptObject creates threads that are required to run
// ChromotingHost and starts/stops the host on those threads. When
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 97f7a742..0567506 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -640,8 +640,9 @@
'remoting_host',
'remoting_host_event_logger',
'remoting_host_logging',
- 'remoting_infoplist_strings',
'remoting_host_setup_base',
+ 'remoting_infoplist_strings',
+ 'remoting_it2me_host_static',
'remoting_jingle_glue',
'remoting_resources',
],
@@ -732,6 +733,27 @@
],
}, # end of target 'remoting_host_plugin'
{
+ 'target_name': 'remoting_it2me_host_static',
+ 'type': 'static_library',
+ 'variables': { 'enable_wexit_time_destructors': 1, },
+ 'dependencies': [
+ '../base/base.gyp:base_i18n',
+ '../net/net.gyp:net',
+ 'remoting_base',
+ 'remoting_host',
+ 'remoting_host_event_logger',
+ 'remoting_host_logging',
+ 'remoting_infoplist_strings',
+ 'remoting_host_setup_base',
+ 'remoting_jingle_glue',
+ 'remoting_resources',
+ ],
+ 'sources': [
+ 'host/it2me/it2me_impl.cc',
+ 'host/it2me/it2me_impl.h',
+ ],
+ }, # end of target 'remoting_it2me_host_static'
+ {
'target_name': 'remoting_infoplist_strings',
'type': 'none',
'dependencies': [