summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authoralexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-17 21:06:24 +0000
committeralexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-17 21:06:24 +0000
commit60ccc243dfbfc86001cf1c0a4b44131a39d7d28d (patch)
tree8834337b7ad8eec985fd783d382734c5d9388eed /remoting
parentf05d582b7e213b15138697c01abf48c652ff271a (diff)
downloadchromium_src-60ccc243dfbfc86001cf1c0a4b44131a39d7d28d.zip
chromium_src-60ccc243dfbfc86001cf1c0a4b44131a39d7d28d.tar.gz
chromium_src-60ccc243dfbfc86001cf1c0a4b44131a39d7d28d.tar.bz2
[Chromoting] Added support of a list of desktop sessions on the daemon side.
DaemonProcess object keeps a list of active desktop sessions, each representing the screen, input devices, etc to be remoted to another machine. The network process is expected to request a desktop session to be opened once a connection has been accepted and closed when the client session is destroyed. This CL includes changes on the daemon side only. BUG=134694 Review URL: https://chromiumcodereview.appspot.com/11017065 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@162520 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r--remoting/host/chromoting_messages.h20
-rw-r--r--remoting/host/daemon_process.cc125
-rw-r--r--remoting/host/daemon_process.h67
-rw-r--r--remoting/host/daemon_process_unittest.cc312
-rw-r--r--remoting/host/daemon_process_win.cc81
-rw-r--r--remoting/host/desktop_session.cc20
-rw-r--r--remoting/host/desktop_session.h42
-rw-r--r--remoting/host/desktop_session_win.cc103
-rw-r--r--remoting/host/desktop_session_win.h77
-rw-r--r--remoting/host/remoting_me2me_host.cc6
-rw-r--r--remoting/host/win/host_service.cc4
-rw-r--r--remoting/host/win/worker_process_launcher.cc6
-rw-r--r--remoting/remoting.gyp26
13 files changed, 815 insertions, 74 deletions
diff --git a/remoting/host/chromoting_messages.h b/remoting/host/chromoting_messages.h
index f997f47..ad85120 100644
--- a/remoting/host/chromoting_messages.h
+++ b/remoting/host/chromoting_messages.h
@@ -10,7 +10,25 @@
#define IPC_MESSAGE_START ChromotingMsgStart
//-----------------------------------------------------------------------------
-// Daemon to Network messages
+// Chromoting messages sent from the daemon to the network process.
// Delivers the host configuration (and updates) to the network process.
IPC_MESSAGE_CONTROL1(ChromotingDaemonNetworkMsg_Configuration, std::string)
+
+// Notifies the network process that the terminal |terminal_id| has been
+// disconnected from the desktop session.
+IPC_MESSAGE_CONTROL1(ChromotingDaemonNetworkMsg_TerminalDisconnected,
+ int /* terminal_id */)
+
+//-----------------------------------------------------------------------------
+// Chromoting messages sent from the network to the daemon process.
+
+// Connects the terminal |terminal_id| (i.e. the remote client) to a desktop
+// session.
+IPC_MESSAGE_CONTROL1(ChromotingNetworkHostMsg_ConnectTerminal,
+ int /* terminal_id */)
+
+// Disconnects the terminal |terminal_id| from the desktop session it was
+// connected to.
+IPC_MESSAGE_CONTROL1(ChromotingNetworkHostMsg_DisconnectTerminal,
+ int /* terminal_id */)
diff --git a/remoting/host/daemon_process.cc b/remoting/host/daemon_process.cc
index 720ed4b..e83db6c 100644
--- a/remoting/host/daemon_process.cc
+++ b/remoting/host/daemon_process.cc
@@ -12,58 +12,111 @@
#include "base/single_thread_task_runner.h"
#include "remoting/host/branding.h"
#include "remoting/host/chromoting_messages.h"
+#include "remoting/host/desktop_session.h"
namespace remoting {
DaemonProcess::~DaemonProcess() {
- CHECK(!config_watcher_.get());
+ DCHECK(!config_watcher_.get());
+ DCHECK(desktop_sessions_.empty());
}
void DaemonProcess::OnConfigUpdated(const std::string& serialized_config) {
+ DCHECK(caller_task_runner()->BelongsToCurrentThread());
+
if (serialized_config_ != serialized_config) {
serialized_config_ = serialized_config;
- Send(new ChromotingDaemonNetworkMsg_Configuration(serialized_config_));
+ SendToNetwork(
+ new ChromotingDaemonNetworkMsg_Configuration(serialized_config_));
}
}
void DaemonProcess::OnConfigWatcherError() {
+ DCHECK(caller_task_runner()->BelongsToCurrentThread());
+
Stop();
}
void DaemonProcess::OnChannelConnected() {
- DCHECK(main_task_runner()->BelongsToCurrentThread());
+ DCHECK(caller_task_runner()->BelongsToCurrentThread());
+
+ DeleteAllDesktopSessions();
+
+ // Reset the last known desktop session ID because no IDs have been allocated
+ // by the the newly started process yet.
+ next_terminal_id_ = 0;
// Send the configuration to the network process.
- Send(new ChromotingDaemonNetworkMsg_Configuration(serialized_config_));
+ SendToNetwork(
+ new ChromotingDaemonNetworkMsg_Configuration(serialized_config_));
}
bool DaemonProcess::OnMessageReceived(const IPC::Message& message) {
- DCHECK(main_task_runner()->BelongsToCurrentThread());
-
- return false;
+ DCHECK(caller_task_runner()->BelongsToCurrentThread());
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(DaemonProcess, message)
+ IPC_MESSAGE_HANDLER(ChromotingNetworkHostMsg_ConnectTerminal,
+ CreateDesktopSession)
+ IPC_MESSAGE_HANDLER(ChromotingNetworkHostMsg_DisconnectTerminal,
+ CloseDesktopSession)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
}
void DaemonProcess::OnPermanentError() {
- DCHECK(main_task_runner()->BelongsToCurrentThread());
-
+ DCHECK(caller_task_runner()->BelongsToCurrentThread());
Stop();
}
+void DaemonProcess::CloseDesktopSession(int terminal_id) {
+ DCHECK(caller_task_runner()->BelongsToCurrentThread());
+
+ // Validate the supplied terminal ID. An attempt to close a desktop session
+ // with an ID that couldn't possibly have been allocated is considered
+ // a protocol error and the network process will be restarted.
+ if (!IsTerminalIdKnown(terminal_id)) {
+ LOG(ERROR) << "An invalid terminal ID. terminal_id=" << terminal_id;
+ RestartNetworkProcess();
+ DeleteAllDesktopSessions();
+ return;
+ }
+
+ DesktopSessionList::iterator i;
+ for (i = desktop_sessions_.begin(); i != desktop_sessions_.end(); ++i) {
+ if ((*i)->id() == terminal_id) {
+ break;
+ }
+ }
+
+ // It is OK if the desktop session ID wasn't found. There is a race between
+ // the network and daemon processes. Each frees its own recources first and
+ // notifies the other party if there was something to clean up.
+ if (i == desktop_sessions_.end())
+ return;
+
+ delete *i;
+ desktop_sessions_.erase(i);
+
+ VLOG(1) << "Daemon: closed desktop session " << terminal_id;
+ SendToNetwork(
+ new ChromotingDaemonNetworkMsg_TerminalDisconnected(terminal_id));
+}
+
DaemonProcess::DaemonProcess(
- scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const base::Closure& stopped_callback)
- : Stoppable(main_task_runner, stopped_callback),
- main_task_runner_(main_task_runner),
- io_task_runner_(io_task_runner) {
- // Initialize on the same thread that will be used for shutting down.
- main_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&DaemonProcess::Initialize, base::Unretained(this)));
+ : Stoppable(caller_task_runner, stopped_callback),
+ caller_task_runner_(caller_task_runner),
+ io_task_runner_(io_task_runner),
+ next_terminal_id_(0) {
+ DCHECK(caller_task_runner->BelongsToCurrentThread());
}
void DaemonProcess::Initialize() {
- DCHECK(main_task_runner()->BelongsToCurrentThread());
+ DCHECK(caller_task_runner()->BelongsToCurrentThread());
// Get the name of the host configuration file.
FilePath default_config_dir = remoting::GetConfigDir();
@@ -74,7 +127,7 @@ void DaemonProcess::Initialize() {
}
// Start watching the host configuration file.
- config_watcher_.reset(new ConfigFileWatcher(main_task_runner(),
+ config_watcher_.reset(new ConfigFileWatcher(caller_task_runner(),
io_task_runner(),
this));
config_watcher_->Watch(config_path);
@@ -83,11 +136,43 @@ void DaemonProcess::Initialize() {
LaunchNetworkProcess();
}
+bool DaemonProcess::IsTerminalIdKnown(int terminal_id) {
+ return terminal_id < next_terminal_id_;
+}
+
+void DaemonProcess::CreateDesktopSession(int terminal_id) {
+ DCHECK(caller_task_runner()->BelongsToCurrentThread());
+
+ // Validate the supplied terminal ID. An attempt to create a desktop session
+ // with an ID that could possibly have been allocated already is considered
+ // a protocol error and the network process will be restarted.
+ if (IsTerminalIdKnown(terminal_id)) {
+ LOG(ERROR) << "An invalid terminal ID. terminal_id=" << terminal_id;
+ RestartNetworkProcess();
+ DeleteAllDesktopSessions();
+ return;
+ }
+
+ VLOG(1) << "Daemon: opened desktop session " << terminal_id;
+ desktop_sessions_.push_back(
+ DoCreateDesktopSession(terminal_id).release());
+ next_terminal_id_ = std::max(next_terminal_id_, terminal_id + 1);
+}
+
void DaemonProcess::DoStop() {
- DCHECK(main_task_runner()->BelongsToCurrentThread());
+ DCHECK(caller_task_runner()->BelongsToCurrentThread());
config_watcher_.reset();
+ DeleteAllDesktopSessions();
+
CompleteStopping();
}
+void DaemonProcess::DeleteAllDesktopSessions() {
+ while (!desktop_sessions_.empty()) {
+ delete desktop_sessions_.front();
+ desktop_sessions_.pop_front();
+ }
+}
+
} // namespace remoting
diff --git a/remoting/host/daemon_process.h b/remoting/host/daemon_process.h
index b7bcc55..c2ba4e2 100644
--- a/remoting/host/daemon_process.h
+++ b/remoting/host/daemon_process.h
@@ -5,6 +5,8 @@
#ifndef REMOTING_HOST_DAEMON_PROCESS_H_
#define REMOTING_HOST_DAEMON_PROCESS_H_
+#include <list>
+
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
@@ -23,19 +25,26 @@ class SingleThreadTaskRunner;
namespace remoting {
+class DesktopSession;
+
// This class implements core of the daemon process. It manages the networking
-// process running at lower privileges and maintains the list of virtual
-// terminals.
+// process running at lower privileges and maintains the list of desktop
+// sessions.
class DaemonProcess
: public Stoppable,
public ConfigFileWatcher::Delegate,
public WorkerProcessIpcDelegate {
public:
+ typedef std::list<DesktopSession*> DesktopSessionList;
+
virtual ~DaemonProcess();
- // Creates a platform-specific implementation of the daemon process object.
+ // Creates a platform-specific implementation of the daemon process object
+ // passing relevant task runners. Public methods of this class must be called
+ // on the |caller_task_runner| thread. |io_task_runner| is used to handle IPC
+ // and background I/O tasks.
static scoped_ptr<DaemonProcess> Create(
- scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const base::Closure& stopped_callback);
@@ -50,41 +59,73 @@ class DaemonProcess
// Sends an IPC message to the network process. The message will be dropped
// unless the network process is connected over the IPC channel.
- virtual void Send(IPC::Message* message) = 0;
+ virtual void SendToNetwork(IPC::Message* message) = 0;
+
+ // Closes the desktop session identified by |terminal_id|.
+ void CloseDesktopSession(int terminal_id);
protected:
- DaemonProcess(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ DaemonProcess(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const base::Closure& stopped_callback);
- // Reads the host configuration and launches the networking process.
+ // Reads the host configuration and launches the network process.
void Initialize();
+ // Creates a desktop session and assigns a unique ID to it.
+ void CreateDesktopSession(int terminal_id);
+
+ // Returns true if |terminal_id| is considered to be known. I.e. it is
+ // less or equal to the highest ID we have seen so far.
+ bool IsTerminalIdKnown(int terminal_id);
+
// Stoppable implementation.
virtual void DoStop() OVERRIDE;
+ // Creates a platform-specific desktop session and assigns a unique ID to it.
+ virtual scoped_ptr<DesktopSession> DoCreateDesktopSession(
+ int terminal_id) = 0;
+
// Launches the network process and establishes an IPC channel with it.
virtual void LaunchNetworkProcess() = 0;
- scoped_refptr<base::SingleThreadTaskRunner> main_task_runner() {
- return main_task_runner_;
+ // Restart the network process.
+ virtual void RestartNetworkProcess() = 0;
+
+ scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner() {
+ return caller_task_runner_;
}
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner() {
return io_task_runner_;
}
+ // Let the test code analyze the list of desktop sessions.
+ friend class DaemonProcessTest;
+ const DesktopSessionList& desktop_sessions() const {
+ return desktop_sessions_;
+ }
+
private:
+ // Deletes all desktop sessions.
+ void DeleteAllDesktopSessions();
+
+ // Task runner on which public methods of this class must be called.
+ scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
+
+ // Handles IPC and background I/O tasks.
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+
scoped_ptr<ConfigFileWatcher> config_watcher_;
// The configuration file contents.
std::string serialized_config_;
- // The main task runner. Typically it is the UI message loop.
- scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ // The list of active desktop sessions.
+ DesktopSessionList desktop_sessions_;
- // Handles IPC and background I/O tasks.
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+ // The highest desktop session ID that has been seen so far.
+ int next_terminal_id_;
DISALLOW_COPY_AND_ASSIGN(DaemonProcess);
};
diff --git a/remoting/host/daemon_process_unittest.cc b/remoting/host/daemon_process_unittest.cc
new file mode 100644
index 0000000..29a1dd2
--- /dev/null
+++ b/remoting/host/daemon_process_unittest.cc
@@ -0,0 +1,312 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_macros.h"
+#include "remoting/base/auto_thread_task_runner.h"
+#include "remoting/host/chromoting_messages.h"
+#include "remoting/host/daemon_process.h"
+#include "remoting/host/desktop_session.h"
+#include "testing/gmock_mutant.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::AnyNumber;
+using testing::InSequence;
+
+namespace remoting {
+
+namespace {
+
+enum Messages {
+ kMessageConfiguration = ChromotingDaemonNetworkMsg_Configuration::ID,
+ kMessageConnectTerminal = ChromotingNetworkHostMsg_ConnectTerminal::ID,
+ kMessageDisconnectTerminal = ChromotingNetworkHostMsg_DisconnectTerminal::ID,
+ kMessageTerminalDisconnected =
+ ChromotingDaemonNetworkMsg_TerminalDisconnected::ID
+};
+
+// Provides a public constructor allowing the test to create instances of
+// DesktopSession directly.
+class FakeDesktopSession : public DesktopSession {
+ public:
+ FakeDesktopSession(DaemonProcess* daemon_process, int id);
+ virtual ~FakeDesktopSession();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FakeDesktopSession);
+};
+
+class MockDaemonProcess : public DaemonProcess {
+ public:
+ MockDaemonProcess(
+ scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
+ const base::Closure& stopped_callback);
+ virtual ~MockDaemonProcess();
+
+ virtual scoped_ptr<DesktopSession> DoCreateDesktopSession(
+ int terminal_id) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual void SendToNetwork(IPC::Message* message) OVERRIDE;
+
+ MOCK_METHOD1(Received, void(const IPC::Message&));
+ MOCK_METHOD1(Sent, void(const IPC::Message&));
+
+ MOCK_METHOD1(DoCreateDesktopSessionPtr, DesktopSession*(int));
+ MOCK_METHOD0(LaunchNetworkProcess, void());
+ MOCK_METHOD0(RestartNetworkProcess, void());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockDaemonProcess);
+};
+
+FakeDesktopSession::FakeDesktopSession(DaemonProcess* daemon_process, int id)
+ : DesktopSession(daemon_process, id) {
+}
+
+FakeDesktopSession::~FakeDesktopSession() {
+}
+
+MockDaemonProcess::MockDaemonProcess(
+ scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
+ const base::Closure& stopped_callback)
+ : DaemonProcess(caller_task_runner, io_task_runner, stopped_callback) {
+}
+
+MockDaemonProcess::~MockDaemonProcess() {
+}
+
+scoped_ptr<DesktopSession> MockDaemonProcess::DoCreateDesktopSession(
+ int terminal_id) {
+ return scoped_ptr<DesktopSession>(DoCreateDesktopSessionPtr(terminal_id));
+}
+
+bool MockDaemonProcess::OnMessageReceived(const IPC::Message& message) {
+ // Notify the mock method.
+ Received(message);
+
+ // Call the actual handler.
+ return DaemonProcess::OnMessageReceived(message);
+}
+
+void MockDaemonProcess::SendToNetwork(IPC::Message* message) {
+ // Notify the mock method.
+ Sent(*message);
+}
+
+} // namespace
+
+class DaemonProcessTest : public testing::Test {
+ public:
+ DaemonProcessTest();
+ virtual ~DaemonProcessTest();
+
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+
+ // DaemonProcess mocks
+ DesktopSession* DoCreateDesktopSession(int terminal_id);
+ void LaunchNetworkProcess();
+
+ // Deletes |daemon_process_|.
+ void DeleteDaemonProcess();
+
+ // Quits |message_loop_|.
+ void QuitMessageLoop();
+
+ void StartDaemonProcess();
+
+ const DaemonProcess::DesktopSessionList& desktop_sessions() const {
+ return daemon_process_->desktop_sessions();
+ }
+
+ protected:
+ MessageLoop message_loop_;
+
+ scoped_ptr<MockDaemonProcess> daemon_process_;
+ int terminal_id_;
+};
+
+
+DaemonProcessTest::DaemonProcessTest()
+ : message_loop_(MessageLoop::TYPE_IO),
+ terminal_id_(0) {
+}
+
+DaemonProcessTest::~DaemonProcessTest() {
+}
+
+void DaemonProcessTest::SetUp() {
+ scoped_refptr<AutoThreadTaskRunner> task_runner = new AutoThreadTaskRunner(
+ message_loop_.message_loop_proxy(),
+ base::Bind(&DaemonProcessTest::QuitMessageLoop,
+ base::Unretained(this)));
+ daemon_process_.reset(
+ new MockDaemonProcess(task_runner, task_runner,
+ base::Bind(&DaemonProcessTest::DeleteDaemonProcess,
+ base::Unretained(this))));
+
+ // Set up daemon process mocks.
+ EXPECT_CALL(*daemon_process_, DoCreateDesktopSessionPtr(_))
+ .Times(AnyNumber())
+ .WillRepeatedly(Invoke(this, &DaemonProcessTest::DoCreateDesktopSession));
+ EXPECT_CALL(*daemon_process_, LaunchNetworkProcess())
+ .Times(AnyNumber())
+ .WillRepeatedly(Invoke(this, &DaemonProcessTest::LaunchNetworkProcess));
+}
+
+void DaemonProcessTest::TearDown() {
+ daemon_process_->Stop();
+ message_loop_.Run();
+}
+
+DesktopSession* DaemonProcessTest::DoCreateDesktopSession(int terminal_id) {
+ return new FakeDesktopSession(daemon_process_.get(), terminal_id);
+}
+
+void DaemonProcessTest::LaunchNetworkProcess() {
+ terminal_id_ = 0;
+ daemon_process_->OnChannelConnected();
+}
+
+void DaemonProcessTest::DeleteDaemonProcess() {
+ daemon_process_.reset();
+}
+
+void DaemonProcessTest::QuitMessageLoop() {
+ message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
+}
+
+void DaemonProcessTest::StartDaemonProcess() {
+ // DaemonProcess::Initialize() sets up the config watcher that this test does
+ // not support. Launch the process directly.
+ daemon_process_->LaunchNetworkProcess();
+}
+
+MATCHER_P(Message, type, "") {
+ return arg.type() == static_cast<uint32>(type);
+}
+
+TEST_F(DaemonProcessTest, OpenClose) {
+ InSequence s;
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageDisconnectTerminal)));
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageTerminalDisconnected)));
+
+ StartDaemonProcess();
+
+ int id = terminal_id_++;
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_ConnectTerminal(id)));
+ EXPECT_EQ(1u, desktop_sessions().size());
+ EXPECT_EQ(id, desktop_sessions().front()->id());
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_DisconnectTerminal(id)));
+ EXPECT_TRUE(desktop_sessions().empty());
+}
+
+TEST_F(DaemonProcessTest, CallCloseDesktopSession) {
+ InSequence s;
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageTerminalDisconnected)));
+
+ StartDaemonProcess();
+
+ int id = terminal_id_++;
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_ConnectTerminal(id)));
+ EXPECT_EQ(1u, desktop_sessions().size());
+ EXPECT_EQ(id, desktop_sessions().front()->id());
+
+ daemon_process_->CloseDesktopSession(id);
+ EXPECT_TRUE(desktop_sessions().empty());
+}
+
+// Sends two CloseDesktopSession messages and expects the second one to be
+// ignored.
+TEST_F(DaemonProcessTest, DoubleDisconnectTerminal) {
+ InSequence s;
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageDisconnectTerminal)));
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageTerminalDisconnected)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageDisconnectTerminal)));
+
+ StartDaemonProcess();
+
+ int id = terminal_id_++;
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_ConnectTerminal(id)));
+ EXPECT_EQ(1u, desktop_sessions().size());
+ EXPECT_EQ(id, desktop_sessions().front()->id());
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_DisconnectTerminal(id)));
+ EXPECT_TRUE(desktop_sessions().empty());
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_DisconnectTerminal(id)));
+ EXPECT_TRUE(desktop_sessions().empty());
+}
+
+// Tries to close an invalid terminal ID and expects the network process to be
+// restarted.
+TEST_F(DaemonProcessTest, InvalidDisconnectTerminal) {
+ InSequence s;
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageDisconnectTerminal)));
+ EXPECT_CALL(*daemon_process_, RestartNetworkProcess())
+ .WillRepeatedly(Invoke(this, &DaemonProcessTest::LaunchNetworkProcess));
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
+
+ StartDaemonProcess();
+
+ int id = terminal_id_++;
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_DisconnectTerminal(id)));
+ EXPECT_TRUE(desktop_sessions().empty());
+ EXPECT_EQ(0, terminal_id_);
+}
+
+// Tries to open an invalid terminal ID and expects the network process to be
+// restarted.
+TEST_F(DaemonProcessTest, InvalidConnectTerminal) {
+ InSequence s;
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
+ EXPECT_CALL(*daemon_process_, RestartNetworkProcess())
+ .WillRepeatedly(Invoke(this, &DaemonProcessTest::LaunchNetworkProcess));
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
+
+ StartDaemonProcess();
+
+ int id = terminal_id_++;
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_ConnectTerminal(id)));
+ EXPECT_EQ(1u, desktop_sessions().size());
+ EXPECT_EQ(id, desktop_sessions().front()->id());
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_ConnectTerminal(id)));
+ EXPECT_TRUE(desktop_sessions().empty());
+ EXPECT_EQ(0, terminal_id_);
+}
+
+} // namespace remoting
diff --git a/remoting/host/daemon_process_win.cc b/remoting/host/daemon_process_win.cc
index 0a9329a..cb81b4a 100644
--- a/remoting/host/daemon_process_win.cc
+++ b/remoting/host/daemon_process_win.cc
@@ -15,8 +15,13 @@
#include "base/timer.h"
#include "base/utf_string_conversions.h"
#include "base/win/scoped_handle.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_macros.h"
+#include "remoting/host/chromoting_messages.h"
+#include "remoting/host/desktop_session_win.h"
#include "remoting/host/host_exit_codes.h"
#include "remoting/host/ipc_consts.h"
+#include "remoting/host/win/host_service.h"
#include "remoting/host/win/launch_process_with_token.h"
#include "remoting/host/win/unprivileged_process_delegate.h"
#include "remoting/host/win/worker_process_launcher.h"
@@ -26,35 +31,41 @@ using base::TimeDelta;
namespace remoting {
+class WtsConsoleMonitor;
+
class DaemonProcessWin : public DaemonProcess {
public:
- DaemonProcessWin(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- const base::Closure& stopped_callback);
+ DaemonProcessWin(
+ scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
+ const base::Closure& stopped_callback);
virtual ~DaemonProcessWin();
// Sends an IPC message to the worker process. This method can be called only
// after successful Start() and until Stop() is called or an error occurred.
- virtual void Send(IPC::Message* message) OVERRIDE;
+ virtual void SendToNetwork(IPC::Message* message) OVERRIDE;
protected:
// Stoppable implementation.
virtual void DoStop() OVERRIDE;
// DaemonProcess implementation.
+ virtual scoped_ptr<DesktopSession> DoCreateDesktopSession(
+ int terminal_id) OVERRIDE;
virtual void LaunchNetworkProcess() OVERRIDE;
+ virtual void RestartNetworkProcess() OVERRIDE;
private:
- scoped_ptr<WorkerProcessLauncher> launcher_;
+ scoped_ptr<WorkerProcessLauncher> network_launcher_;
DISALLOW_COPY_AND_ASSIGN(DaemonProcessWin);
};
DaemonProcessWin::DaemonProcessWin(
- scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const base::Closure& stopped_callback)
- : DaemonProcess(main_task_runner, io_task_runner, stopped_callback) {
+ : DaemonProcess(caller_task_runner, io_task_runner, stopped_callback) {
}
DaemonProcessWin::~DaemonProcessWin() {
@@ -64,9 +75,33 @@ DaemonProcessWin::~DaemonProcessWin() {
CHECK_EQ(stoppable_state(), Stoppable::kStopped);
}
+void DaemonProcessWin::SendToNetwork(IPC::Message* message) {
+ if (network_launcher_) {
+ network_launcher_->Send(message);
+ } else {
+ delete message;
+ }
+}
+
+void DaemonProcessWin::DoStop() {
+ DCHECK(caller_task_runner()->BelongsToCurrentThread());
+
+ network_launcher_.reset();
+ DaemonProcess::DoStop();
+}
+
+scoped_ptr<DesktopSession> DaemonProcessWin::DoCreateDesktopSession(
+ int terminal_id) {
+ DCHECK(caller_task_runner()->BelongsToCurrentThread());
+
+ return scoped_ptr<DesktopSession>(new DesktopSessionWin(
+ caller_task_runner(), io_task_runner(), this, terminal_id,
+ HostService::GetInstance()));
+}
+
void DaemonProcessWin::LaunchNetworkProcess() {
- DCHECK(main_task_runner()->BelongsToCurrentThread());
- DCHECK(launcher_.get() == NULL);
+ DCHECK(caller_task_runner()->BelongsToCurrentThread());
+ DCHECK(!network_launcher_);
// Construct the host binary name.
FilePath host_binary;
@@ -76,33 +111,27 @@ void DaemonProcessWin::LaunchNetworkProcess() {
}
scoped_ptr<UnprivilegedProcessDelegate> delegate(
- new UnprivilegedProcessDelegate(main_task_runner(), io_task_runner(),
+ new UnprivilegedProcessDelegate(caller_task_runner(), io_task_runner(),
host_binary));
- launcher_.reset(new WorkerProcessLauncher(
- main_task_runner(), delegate.Pass(), this));
-}
-
-void DaemonProcessWin::Send(IPC::Message* message) {
- if (launcher_.get() != NULL) {
- launcher_->Send(message);
- } else {
- delete message;
- }
+ network_launcher_.reset(new WorkerProcessLauncher(
+ caller_task_runner(), delegate.Pass(), this));
}
-void DaemonProcessWin::DoStop() {
- DCHECK(main_task_runner()->BelongsToCurrentThread());
+void DaemonProcessWin::RestartNetworkProcess() {
+ DCHECK(caller_task_runner()->BelongsToCurrentThread());
- launcher_.reset();
- DaemonProcess::DoStop();
+ network_launcher_.reset();
+ LaunchNetworkProcess();
}
scoped_ptr<DaemonProcess> DaemonProcess::Create(
- scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const base::Closure& stopped_callback) {
scoped_ptr<DaemonProcessWin> daemon_process(
- new DaemonProcessWin(main_task_runner, io_task_runner, stopped_callback));
+ new DaemonProcessWin(caller_task_runner, io_task_runner,
+ stopped_callback));
+ daemon_process->Initialize();
return daemon_process.PassAs<DaemonProcess>();
}
diff --git a/remoting/host/desktop_session.cc b/remoting/host/desktop_session.cc
new file mode 100644
index 0000000..b8a9a9d
--- /dev/null
+++ b/remoting/host/desktop_session.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/desktop_session.h"
+
+#include "base/single_thread_task_runner.h"
+#include "remoting/host/daemon_process.h"
+
+namespace remoting {
+
+DesktopSession::~DesktopSession() {
+}
+
+DesktopSession::DesktopSession(DaemonProcess* daemon_process, int id)
+ : daemon_process_(daemon_process),
+ id_(id) {
+}
+
+} // namespace remoting
diff --git a/remoting/host/desktop_session.h b/remoting/host/desktop_session.h
new file mode 100644
index 0000000..f59818b
--- /dev/null
+++ b/remoting/host/desktop_session.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_HOST_DESKTOP_SESSION_H_
+#define REMOTING_HOST_DESKTOP_SESSION_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+
+namespace remoting {
+
+class DaemonProcess;
+
+// Represents the desktop session for a connected terminal. Each desktop session
+// has a unique identifier used by cross-platform code to refer to it.
+class DesktopSession {
+ public:
+ virtual ~DesktopSession();
+
+ int id() const { return id_; }
+
+ protected:
+ // Creates a terminal and assigns a unique identifier to it. |deamon_process|
+ // must outlive |this|.
+ DesktopSession(DaemonProcess* daemon_process, int id);
+
+ DaemonProcess* daemon_process() const { return daemon_process_; }
+
+ private:
+ // The owner of |this|.
+ DaemonProcess* const daemon_process_;
+
+ // A unique identifier of the terminal.
+ const int id_;
+
+ DISALLOW_COPY_AND_ASSIGN(DesktopSession);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_HOST_DESKTOP_SESSION_H_
diff --git a/remoting/host/desktop_session_win.cc b/remoting/host/desktop_session_win.cc
new file mode 100644
index 0000000..6224c3d
--- /dev/null
+++ b/remoting/host/desktop_session_win.cc
@@ -0,0 +1,103 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/desktop_session_win.h"
+
+#include "base/path_service.h"
+#include "base/single_thread_task_runner.h"
+#include "remoting/host/daemon_process.h"
+#include "remoting/host/win/worker_process_launcher.h"
+#include "remoting/host/win/wts_console_monitor.h"
+#include "remoting/host/win/wts_session_process_delegate.h"
+
+namespace {
+
+const FilePath::CharType kDesktopBinaryName[] =
+ FILE_PATH_LITERAL("remoting_desktop.exe");
+
+// The security descriptor of the daemon IPC endpoint. It gives full access
+// to LocalSystem and denies access by anyone else.
+const char kDaemonIpcSecurityDescriptor[] = "O:SYG:SYD:(A;;GA;;;SY)";
+
+} // namespace
+
+namespace remoting {
+
+DesktopSessionWin::DesktopSessionWin(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
+ DaemonProcess* daemon_process,
+ int id,
+ WtsConsoleMonitor* monitor)
+ : DesktopSession(daemon_process, id),
+ main_task_runner_(main_task_runner),
+ io_task_runner_(io_task_runner),
+ monitor_(monitor) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ monitor_->AddWtsConsoleObserver(this);
+}
+
+DesktopSessionWin::~DesktopSessionWin() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ launcher_.reset();
+ monitor_->RemoveWtsConsoleObserver(this);
+}
+
+void DesktopSessionWin::OnChannelConnected() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+}
+
+bool DesktopSessionWin::OnMessageReceived(const IPC::Message& message) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ // TODO(alexeypa): Process ChromotingDesktopHostMsg_Initialized messages here.
+ // See http://crbug.com/134694.
+ return false;
+}
+
+void DesktopSessionWin::OnPermanentError() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ launcher_.reset();
+
+ // This call will delete |this| so it should be at the very end of the method.
+ daemon_process()->CloseDesktopSession(id());
+}
+
+void DesktopSessionWin::OnSessionAttached(uint32 session_id) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(launcher_.get() == NULL);
+
+ // Construct the host binary name.
+ if (desktop_binary_.empty()) {
+ FilePath dir_path;
+ if (!PathService::Get(base::DIR_EXE, &dir_path)) {
+ LOG(ERROR) << "Failed to get the executable file name.";
+ OnPermanentError();
+ return;
+ }
+ desktop_binary_ = dir_path.Append(kDesktopBinaryName);
+ }
+
+ // Create a delegate to launch a process into the session.
+ scoped_ptr<WtsSessionProcessDelegate> delegate(
+ new WtsSessionProcessDelegate(main_task_runner_, io_task_runner_,
+ desktop_binary_, session_id,
+ true, kDaemonIpcSecurityDescriptor));
+
+ // Create a launcher for the desktop process, using the per-session delegate.
+ launcher_.reset(new WorkerProcessLauncher(
+ main_task_runner_, delegate.Pass(), this));
+}
+
+void DesktopSessionWin::OnSessionDetached() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(launcher_.get() != NULL);
+
+ launcher_.reset();
+}
+
+} // namespace remoting
diff --git a/remoting/host/desktop_session_win.h b/remoting/host/desktop_session_win.h
new file mode 100644
index 0000000..f958225
--- /dev/null
+++ b/remoting/host/desktop_session_win.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_HOST_DESKTOP_SESSION_WIN_H_
+#define REMOTING_HOST_DESKTOP_SESSION_WIN_H_
+
+#include "base/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "remoting/host/desktop_session.h"
+#include "remoting/host/win/wts_console_observer.h"
+#include "remoting/host/worker_process_ipc_delegate.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace remoting {
+
+class DaemonProcess;
+class WorkerProcessLauncher;
+class WtsConsoleMonitor;
+
+// DesktopSession implementation which attaches to the host's physical console.
+// Receives IPC messages from the desktop process, running in the console
+// session, via |WorkerProcessIpcDelegate|, and monitors console session
+// attach/detach events via |WtsConsoleObserer|.
+// TODO(alexeypa): replace |WtsConsoleObserver| with an interface capable of
+// monitoring both the console and RDP connections. See http://crbug.com/137696.
+class DesktopSessionWin
+ : public DesktopSession,
+ public WorkerProcessIpcDelegate,
+ public WtsConsoleObserver {
+ public:
+ // Passes the owning |daemon_process|, a unique identifier of the desktop
+ // session |id| and the interface for monitoring console session attach/detach
+ // events. Both |daemon_process| and |monitor| must outlive |this|.
+ DesktopSessionWin(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
+ DaemonProcess* daemon_process,
+ int id,
+ WtsConsoleMonitor* monitor);
+ virtual ~DesktopSessionWin();
+
+ // WorkerProcessIpcDelegate implementation.
+ virtual void OnChannelConnected() OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual void OnPermanentError() OVERRIDE;
+
+ // WtsConsoleObserver implementation.
+ virtual void OnSessionAttached(uint32 session_id) OVERRIDE;
+ virtual void OnSessionDetached() OVERRIDE;
+
+ private:
+ // Task runner on which public methods of this class should be called.
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+
+ // Message loop used by the IPC channel.
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+
+ // Contains the full path to the desktop binary.
+ FilePath desktop_binary_;
+
+ // Launches and monitors the desktop process.
+ scoped_ptr<WorkerProcessLauncher> launcher_;
+
+ // Pointer used to unsubscribe from session attach and detach events.
+ WtsConsoleMonitor* monitor_;
+
+ DISALLOW_COPY_AND_ASSIGN(DesktopSessionWin);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_HOST_DESKTOP_SESSION_WIN_H_
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc
index 733b85f..b3b9fe0 100644
--- a/remoting/host/remoting_me2me_host.cc
+++ b/remoting/host/remoting_me2me_host.cc
@@ -298,9 +298,9 @@ class HostProcess
#if defined(REMOTING_MULTI_PROCESS)
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(HostProcess, message)
- IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_Configuration,
- OnConfigUpdated)
- IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_Configuration,
+ OnConfigUpdated)
+ IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
#else // !defined(REMOTING_MULTI_PROCESS)
diff --git a/remoting/host/win/host_service.cc b/remoting/host/win/host_service.cc
index d8ff0d1..5de9c0f 100644
--- a/remoting/host/win/host_service.cc
+++ b/remoting/host/win/host_service.cc
@@ -114,6 +114,8 @@ void HostService::AddWtsConsoleObserver(WtsConsoleObserver* observer) {
DCHECK(main_task_runner_->BelongsToCurrentThread());
console_observers_.AddObserver(observer);
+ if (console_session_id_ != kInvalidSessionId)
+ observer->OnSessionAttached(console_session_id_);
}
void HostService::RemoveWtsConsoleObserver(WtsConsoleObserver* observer) {
@@ -128,6 +130,8 @@ void HostService::OnChildStopped() {
}
void HostService::OnSessionChange() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
// WTSGetActiveConsoleSessionId is a very cheap API. It basically reads
// a single value from shared memory. Therefore it is better to check if
// the console session is still the same every time a session change
diff --git a/remoting/host/win/worker_process_launcher.cc b/remoting/host/win/worker_process_launcher.cc
index e8b698a..63840a6 100644
--- a/remoting/host/win/worker_process_launcher.cc
+++ b/remoting/host/win/worker_process_launcher.cc
@@ -186,7 +186,11 @@ void WorkerProcessLauncher::Core::Stop() {
void WorkerProcessLauncher::Core::Send(IPC::Message* message) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
- launcher_delegate_->Send(message);
+ if (ipc_enabled_) {
+ launcher_delegate_->Send(message);
+ } else {
+ delete message;
+ }
}
void WorkerProcessLauncher::Core::OnObjectSignaled(HANDLE object) {
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 6e3365e..9fbb51a 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -626,6 +626,10 @@
'host/daemon_process.cc',
'host/daemon_process.h',
'host/daemon_process_win.cc',
+ 'host/desktop_session.cc',
+ 'host/desktop_session.h',
+ 'host/desktop_session_win.cc',
+ 'host/desktop_session_win.h',
'host/host_exit_codes.h',
'host/ipc_consts.cc',
'host/ipc_consts.h',
@@ -1426,6 +1430,7 @@
'remoting_protocol',
'differ_block',
'../crypto/crypto.gyp:crypto',
+ '../ipc/ipc.gyp:ipc',
],
'defines': [
'VERSION=<(version_full)',
@@ -1446,6 +1451,8 @@
'host/chromoting_host.h',
'host/chromoting_host_context.cc',
'host/chromoting_host_context.h',
+ 'host/chromoting_messages.cc',
+ 'host/chromoting_messages.h',
'host/client_session.cc',
'host/client_session.h',
'host/clipboard.h',
@@ -1626,12 +1633,6 @@
],
},
}],
- ['OS=="win"', {
- 'sources': [
- 'host/chromoting_messages.cc',
- 'host/chromoting_messages.h',
- ],
- }],
],
}, # end of target 'remoting_host'
@@ -1700,7 +1701,6 @@
'../base/base.gyp:base',
'../base/base.gyp:base_i18n',
'../google_apis/google_apis.gyp:google_apis',
- '../ipc/ipc.gyp:ipc',
'../media/media.gyp:media',
'../net/net.gyp:net',
],
@@ -2031,9 +2031,18 @@
'codec/video_encoder_row_based_unittest.cc',
'codec/video_encoder_vp8_unittest.cc',
'host/audio_capturer_win_unittest.cc',
+ 'host/branding.cc',
+ 'host/branding.h',
'host/chromoting_host_context_unittest.cc',
'host/chromoting_host_unittest.cc',
'host/client_session_unittest.cc',
+ 'host/config_file_watcher.cc',
+ 'host/config_file_watcher.h',
+ 'host/daemon_process.cc',
+ 'host/daemon_process.h',
+ 'host/daemon_process_unittest.cc',
+ 'host/desktop_session.cc',
+ 'host/desktop_session.h',
'host/differ_block_unittest.cc',
'host/differ_unittest.cc',
'host/heartbeat_sender_unittest.cc',
@@ -2101,9 +2110,6 @@
],
'conditions': [
[ 'OS=="win"', {
- 'dependencies': [
- '../ipc/ipc.gyp:ipc',
- ],
'include_dirs': [
'../breakpad/src',
],