summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorjoedow <joedow@chromium.org>2015-03-11 15:08:03 -0700
committerCommit bot <commit-bot@chromium.org>2015-03-11 22:08:58 +0000
commit20fd2b06a7e26f7ad265912f8c8d322c3cb5a306 (patch)
treee463c1119ae6080d73546e81ca022b277ff3c166 /remoting
parent1a2a2738522cb00347f277e8e7d725a4e46ed053 (diff)
downloadchromium_src-20fd2b06a7e26f7ad265912f8c8d322c3cb5a306.zip
chromium_src-20fd2b06a7e26f7ad265912f8c8d322c3cb5a306.tar.gz
chromium_src-20fd2b06a7e26f7ad265912f8c8d322c3cb5a306.tar.bz2
Adding the base ChromotingInstance implementation and unittests. This class will be used by the app remoting test driver in a subsequent checkin.
BUG=464808 Review URL: https://codereview.chromium.org/976233003 Cr-Commit-Position: refs/heads/master@{#320161}
Diffstat (limited to 'remoting')
-rw-r--r--remoting/BUILD.gn15
-rw-r--r--remoting/client/chromoting_client.cc42
-rw-r--r--remoting/client/chromoting_client.h14
-rw-r--r--remoting/client/client_status_logger.cc1
-rw-r--r--remoting/client/server_log_entry_client.cc1
-rw-r--r--remoting/protocol/BUILD.gn2
-rw-r--r--remoting/protocol/connection_to_host.h119
-rw-r--r--remoting/protocol/connection_to_host_impl.cc (renamed from remoting/protocol/connection_to_host.cc)82
-rw-r--r--remoting/protocol/connection_to_host_impl.h136
-rw-r--r--remoting/protocol/fake_connection_to_host.cc118
-rw-r--r--remoting/protocol/fake_connection_to_host.h65
-rw-r--r--remoting/protocol/protocol_mock_objects.h66
-rw-r--r--remoting/remoting_srcs.gypi3
-rw-r--r--remoting/remoting_test.gypi16
-rw-r--r--remoting/test/access_token_fetcher_unittest.cc314
-rw-r--r--remoting/test/remote_connection_observer.h57
-rw-r--r--remoting/test/test_chromoting_client.cc340
-rw-r--r--remoting/test/test_chromoting_client.h113
-rw-r--r--remoting/test/test_chromoting_client_unittest.cc211
-rw-r--r--remoting/test/test_video_renderer.cc49
-rw-r--r--remoting/test/test_video_renderer.h41
21 files changed, 1426 insertions, 379 deletions
diff --git a/remoting/BUILD.gn b/remoting/BUILD.gn
index 047650f..ecf6fb5 100644
--- a/remoting/BUILD.gn
+++ b/remoting/BUILD.gn
@@ -25,8 +25,11 @@ source_set("test_support") {
"signaling/mock_signal_strategy.cc",
"signaling/mock_signal_strategy.h",
"test/access_token_fetcher.cc",
+ "test/access_token_fetcher.h",
"test/app_remoting_test_driver_environment.cc",
+ "test/app_remoting_test_driver_environment.h",
"test/fake_access_token_fetcher.cc",
+ "test/fake_access_token_fetcher.h",
"test/fake_network_dispatcher.cc",
"test/fake_network_dispatcher.h",
"test/fake_network_manager.cc",
@@ -34,14 +37,24 @@ source_set("test_support") {
"test/fake_port_allocator.cc",
"test/fake_port_allocator.h",
"test/fake_remote_host_info_fetcher.cc",
+ "test/fake_remote_host_info_fetcher.h",
"test/fake_socket_factory.cc",
"test/fake_socket_factory.h",
"test/leaky_bucket.cc",
"test/leaky_bucket.h",
"test/mock_access_token_fetcher.cc",
+ "test/mock_access_token_fetcher.h",
"test/refresh_token_store.cc",
+ "test/refresh_token_store.h",
+ "test/remote_connection_observer.h",
"test/remote_host_info.cc",
+ "test/remote_host_info.h",
"test/remote_host_info_fetcher.cc",
+ "test/remote_host_info_fetcher.h",
+ "test/test_chromoting_client.cc",
+ "test/test_chromoting_client.h",
+ "test/test_video_renderer.cc",
+ "test/test_video_renderer.h",
]
deps = [
@@ -76,6 +89,7 @@ if (!is_win && !is_mac) {
"test/access_token_fetcher_unittest.cc",
"test/app_remoting_test_driver_environment_unittest.cc",
"test/remote_host_info_fetcher_unittest.cc",
+ "test/test_chromoting_client_unittest.cc",
]
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
@@ -87,6 +101,7 @@ if (!is_win && !is_mac) {
"//google_apis",
"//remoting/base:unit_tests",
"//remoting/client:unit_tests",
+ "//remoting/protocol:test_support",
"//remoting/protocol:unit_tests",
"//testing/gmock",
"//testing/gtest",
diff --git a/remoting/client/chromoting_client.cc b/remoting/client/chromoting_client.cc
index 1ad7223..a7720d0 100644
--- a/remoting/client/chromoting_client.cc
+++ b/remoting/client/chromoting_client.cc
@@ -24,28 +24,33 @@ namespace remoting {
using protocol::AuthenticationMethod;
-ChromotingClient::ChromotingClient(
- ClientContext* client_context,
- ClientUserInterface* user_interface,
- VideoRenderer* video_renderer,
- scoped_ptr<AudioPlayer> audio_player)
+ChromotingClient::ChromotingClient(ClientContext* client_context,
+ ClientUserInterface* user_interface,
+ VideoRenderer* video_renderer,
+ scoped_ptr<AudioPlayer> audio_player)
: task_runner_(client_context->main_task_runner()),
user_interface_(user_interface),
video_renderer_(video_renderer),
+ connection_(new protocol::ConnectionToHostImpl()),
host_capabilities_received_(false) {
if (audio_player) {
audio_decode_scheduler_.reset(new AudioDecodeScheduler(
client_context->main_task_runner(),
- client_context->audio_decode_task_runner(),
- audio_player.Pass()));
+ client_context->audio_decode_task_runner(), audio_player.Pass()));
}
}
-ChromotingClient::~ChromotingClient() {}
+ChromotingClient::~ChromotingClient() {
+}
void ChromotingClient::SetProtocolConfigForTests(
scoped_ptr<protocol::CandidateSessionConfig> config) {
- connection_.set_candidate_config(config.Pass());
+ connection_->set_candidate_config(config.Pass());
+}
+
+void ChromotingClient::SetConnectionToHostForTests(
+ scoped_ptr<protocol::ConnectionToHost> connection_to_host) {
+ connection_ = connection_to_host.Pass();
}
void ChromotingClient::Start(
@@ -58,12 +63,12 @@ void ChromotingClient::Start(
local_capabilities_ = capabilities;
- connection_.set_client_stub(this);
- connection_.set_clipboard_stub(this);
- connection_.set_video_stub(video_renderer_->GetVideoStub());
- connection_.set_audio_stub(audio_decode_scheduler_.get());
+ connection_->set_client_stub(this);
+ connection_->set_clipboard_stub(this);
+ connection_->set_video_stub(video_renderer_->GetVideoStub());
+ connection_->set_audio_stub(audio_decode_scheduler_.get());
- connection_.Connect(signal_strategy, transport_factory.Pass(),
+ connection_->Connect(signal_strategy, transport_factory.Pass(),
authenticator.Pass(), host_jid, this);
}
@@ -147,10 +152,9 @@ void ChromotingClient::OnAuthenticated() {
DCHECK(task_runner_->BelongsToCurrentThread());
// Initialize the decoder.
- video_renderer_->OnSessionConfig(connection_.config());
- if (connection_.config().is_audio_enabled())
- audio_decode_scheduler_->Initialize(connection_.config());
-
+ video_renderer_->OnSessionConfig(connection_->config());
+ if (connection_->config().is_audio_enabled())
+ audio_decode_scheduler_->Initialize(connection_->config());
}
void ChromotingClient::OnChannelsConnected() {
@@ -161,7 +165,7 @@ void ChromotingClient::OnChannelsConnected() {
protocol::Capabilities capabilities;
capabilities.set_capabilities(local_capabilities_);
- connection_.host_stub()->SetCapabilities(capabilities);
+ connection_->host_stub()->SetCapabilities(capabilities);
}
} // namespace remoting
diff --git a/remoting/client/chromoting_client.h b/remoting/client/chromoting_client.h
index 94c8f4e..b9b7f07 100644
--- a/remoting/client/chromoting_client.h
+++ b/remoting/client/chromoting_client.h
@@ -15,6 +15,7 @@
#include "remoting/protocol/client_stub.h"
#include "remoting/protocol/clipboard_stub.h"
#include "remoting/protocol/connection_to_host.h"
+#include "remoting/protocol/connection_to_host_impl.h"
#include "remoting/protocol/input_stub.h"
#include "remoting/protocol/video_stub.h"
@@ -51,8 +52,11 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
~ChromotingClient() override;
+ // Used to set fake/mock objects for tests which use the ChromotingClient.
void SetProtocolConfigForTests(
scoped_ptr<protocol::CandidateSessionConfig> config);
+ void SetConnectionToHostForTests(
+ scoped_ptr<protocol::ConnectionToHost> connection_to_host);
// Start the client. Must be called on the main thread. |signal_strategy|
// must outlive the client.
@@ -63,14 +67,14 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
const std::string& capabilities);
protocol::ConnectionToHost::State connection_state() const {
- return connection_.state();
+ return connection_->state();
}
protocol::ClipboardStub* clipboard_forwarder() {
- return connection_.clipboard_forwarder();
+ return connection_->clipboard_forwarder();
}
- protocol::HostStub* host_stub() { return connection_.host_stub(); }
- protocol::InputStub* input_stub() { return connection_.input_stub(); }
+ protocol::HostStub* host_stub() { return connection_->host_stub(); }
+ protocol::InputStub* input_stub() { return connection_->input_stub(); }
// ClientStub implementation.
void SetCapabilities(const protocol::Capabilities& capabilities) override;
@@ -103,7 +107,7 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
ClientUserInterface* user_interface_;
VideoRenderer* video_renderer_;
- protocol::ConnectionToHost connection_;
+ scoped_ptr<protocol::ConnectionToHost> connection_;
scoped_ptr<AudioDecodeScheduler> audio_decode_scheduler_;
diff --git a/remoting/client/client_status_logger.cc b/remoting/client/client_status_logger.cc
index 3fdfb56..40b4ecf 100644
--- a/remoting/client/client_status_logger.cc
+++ b/remoting/client/client_status_logger.cc
@@ -4,6 +4,7 @@
#include "remoting/client/client_status_logger.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "base/rand_util.h"
#include "remoting/client/chromoting_stats.h"
diff --git a/remoting/client/server_log_entry_client.cc b/remoting/client/server_log_entry_client.cc
index 5b54c8a..2f781502 100644
--- a/remoting/client/server_log_entry_client.cc
+++ b/remoting/client/server_log_entry_client.cc
@@ -4,6 +4,7 @@
#include "remoting/client/server_log_entry_client.h"
+#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringize_macros.h"
#include "base/strings/stringprintf.h"
diff --git a/remoting/protocol/BUILD.gn b/remoting/protocol/BUILD.gn
index b7bf4bf..41f0e8f 100644
--- a/remoting/protocol/BUILD.gn
+++ b/remoting/protocol/BUILD.gn
@@ -35,6 +35,8 @@ source_set("test_support") {
sources = [
"fake_authenticator.cc",
"fake_authenticator.h",
+ "fake_connection_to_host.cc",
+ "fake_connection_to_host.h",
"fake_datagram_socket.cc",
"fake_datagram_socket.h",
"fake_session.cc",
diff --git a/remoting/protocol/connection_to_host.h b/remoting/protocol/connection_to_host.h
index 605bea3..3b079d1 100644
--- a/remoting/protocol/connection_to_host.h
+++ b/remoting/protocol/connection_to_host.h
@@ -5,51 +5,33 @@
#ifndef REMOTING_PROTOCOL_CONNECTION_TO_HOST_H_
#define REMOTING_PROTOCOL_CONNECTION_TO_HOST_H_
-#include <set>
#include <string>
#include "base/callback_forward.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/threading/non_thread_safe.h"
-#include "remoting/proto/internal.pb.h"
-#include "remoting/protocol/channel_dispatcher_base.h"
-#include "remoting/protocol/clipboard_filter.h"
#include "remoting/protocol/errors.h"
-#include "remoting/protocol/input_filter.h"
-#include "remoting/protocol/message_reader.h"
-#include "remoting/protocol/monitored_video_stub.h"
-#include "remoting/protocol/session.h"
-#include "remoting/protocol/session_config.h"
-#include "remoting/protocol/session_manager.h"
-#include "remoting/signaling/signal_strategy.h"
namespace remoting {
-class XmppProxy;
-class VideoPacket;
+class SignalStrategy;
namespace protocol {
-class AudioReader;
class AudioStub;
class Authenticator;
-class ClientControlDispatcher;
-class ClientEventDispatcher;
+class CandidateSessionConfig;
class ClientStub;
class ClipboardStub;
+class ExtensionMessage;
class HostStub;
class InputStub;
class SessionConfig;
class TransportFactory;
-class ClientVideoDispatcher;
+struct TransportRoute;
class VideoStub;
-class ConnectionToHost : public SignalStrategy::Listener,
- public SessionManager::Listener,
- public Session::EventHandler,
- public ChannelDispatcherBase::EventHandler,
- public base::NonThreadSafe {
+class ConnectionToHost {
public:
// The UI implementations maintain corresponding definitions of this
// enumeration in webapp/client_session.js and
@@ -82,22 +64,22 @@ class ConnectionToHost : public SignalStrategy::Listener,
const protocol::TransportRoute& route) = 0;
};
- ConnectionToHost();
- ~ConnectionToHost() override;
+ virtual ~ConnectionToHost() {}
// Allows to set a custom protocol configuration (e.g. for tests). Cannot be
// called after Connect().
- void set_candidate_config(scoped_ptr<CandidateSessionConfig> config);
+ virtual void set_candidate_config(
+ scoped_ptr<CandidateSessionConfig> config) = 0;
// Set the stubs which will handle messages from the host.
// The caller must ensure that stubs out-live the connection.
// Unless otherwise specified, all stubs must be set before Connect()
// is called.
- void set_client_stub(ClientStub* client_stub);
- void set_clipboard_stub(ClipboardStub* clipboard_stub);
- void set_video_stub(VideoStub* video_stub);
+ virtual void set_client_stub(ClientStub* client_stub) = 0;
+ virtual void set_clipboard_stub(ClipboardStub* clipboard_stub) = 0;
+ virtual void set_video_stub(VideoStub* video_stub) = 0;
// If no audio stub is specified then audio will not be requested.
- void set_audio_stub(AudioStub* audio_stub);
+ virtual void set_audio_stub(AudioStub* audio_stub) = 0;
// Initiates a connection to the host specified by |host_jid|.
// |signal_strategy| is used to signal to the host, and must outlive the
@@ -110,83 +92,18 @@ class ConnectionToHost : public SignalStrategy::Listener,
scoped_ptr<TransportFactory> transport_factory,
scoped_ptr<Authenticator> authenticator,
const std::string& host_jid,
- HostEventCallback* event_callback);
+ HostEventCallback* event_callback) = 0;
// Returns the session configuration that was negotiated with the host.
- virtual const SessionConfig& config();
+ virtual const SessionConfig& config() = 0;
// Stubs for sending data to the host.
- virtual ClipboardStub* clipboard_forwarder();
- virtual HostStub* host_stub();
- virtual InputStub* input_stub();
-
- // SignalStrategy::StatusObserver interface.
- void OnSignalStrategyStateChange(SignalStrategy::State state) override;
- bool OnSignalStrategyIncomingStanza(const buzz::XmlElement* stanza) override;
-
- // SessionManager::Listener interface.
- void OnSessionManagerReady() override;
- void OnIncomingSession(
- Session* session,
- SessionManager::IncomingSessionResponse* response) override;
-
- // Session::EventHandler interface.
- void OnSessionStateChange(Session::State state) override;
- void OnSessionRouteChange(const std::string& channel_name,
- const TransportRoute& route) override;
-
- // ChannelDispatcherBase::EventHandler interface.
- void OnChannelInitialized(ChannelDispatcherBase* channel_dispatcher) override;
- void OnChannelError(ChannelDispatcherBase* channel_dispatcher,
- ErrorCode error) override;
-
- // MonitoredVideoStub::EventHandler interface.
- virtual void OnVideoChannelStatus(bool active);
+ virtual ClipboardStub* clipboard_forwarder() = 0;
+ virtual HostStub* host_stub() = 0;
+ virtual InputStub* input_stub() = 0;
// Return the current state of ConnectionToHost.
- State state() const;
-
- private:
- void NotifyIfChannelsReady();
-
- void CloseOnError(ErrorCode error);
-
- // Stops writing in the channels.
- void CloseChannels();
-
- void SetState(State state, ErrorCode error);
-
- std::string host_jid_;
- std::string host_public_key_;
- scoped_ptr<Authenticator> authenticator_;
-
- HostEventCallback* event_callback_;
-
- scoped_ptr<CandidateSessionConfig> candidate_config_;
-
- // Stub for incoming messages.
- ClientStub* client_stub_;
- ClipboardStub* clipboard_stub_;
- AudioStub* audio_stub_;
-
- SignalStrategy* signal_strategy_;
- scoped_ptr<SessionManager> session_manager_;
- scoped_ptr<Session> session_;
- scoped_ptr<MonitoredVideoStub> monitored_video_stub_;
-
- scoped_ptr<ClientVideoDispatcher> video_dispatcher_;
- scoped_ptr<AudioReader> audio_reader_;
- scoped_ptr<ClientControlDispatcher> control_dispatcher_;
- scoped_ptr<ClientEventDispatcher> event_dispatcher_;
- ClipboardFilter clipboard_forwarder_;
- InputFilter event_forwarder_;
-
- // Internal state of the connection.
- State state_;
- ErrorCode error_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConnectionToHost);
+ virtual State state() const = 0;
};
} // namespace protocol
diff --git a/remoting/protocol/connection_to_host.cc b/remoting/protocol/connection_to_host_impl.cc
index e2346e6..c524779 100644
--- a/remoting/protocol/connection_to_host.cc
+++ b/remoting/protocol/connection_to_host_impl.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2015 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/protocol/connection_to_host.h"
+#include "remoting/protocol/connection_to_host_impl.h"
#include "base/bind.h"
#include "base/callback.h"
@@ -25,7 +25,7 @@
namespace remoting {
namespace protocol {
-ConnectionToHost::ConnectionToHost()
+ConnectionToHostImpl::ConnectionToHostImpl()
: event_callback_(nullptr),
client_stub_(nullptr),
clipboard_stub_(nullptr),
@@ -35,7 +35,7 @@ ConnectionToHost::ConnectionToHost()
error_(OK) {
}
-ConnectionToHost::~ConnectionToHost() {
+ConnectionToHostImpl::~ConnectionToHostImpl() {
CloseChannels();
if (session_.get())
@@ -48,11 +48,12 @@ ConnectionToHost::~ConnectionToHost() {
signal_strategy_->RemoveListener(this);
}
-void ConnectionToHost::Connect(SignalStrategy* signal_strategy,
- scoped_ptr<TransportFactory> transport_factory,
- scoped_ptr<Authenticator> authenticator,
- const std::string& host_jid,
- HostEventCallback* event_callback) {
+void ConnectionToHostImpl::Connect(
+ SignalStrategy* signal_strategy,
+ scoped_ptr<TransportFactory> transport_factory,
+ scoped_ptr<Authenticator> authenticator,
+ const std::string& host_jid,
+ HostEventCallback* event_callback) {
DCHECK(client_stub_);
DCHECK(clipboard_stub_);
DCHECK(monitored_video_stub_);
@@ -84,54 +85,52 @@ void ConnectionToHost::Connect(SignalStrategy* signal_strategy,
SetState(CONNECTING, OK);
}
-void ConnectionToHost::set_candidate_config(
+void ConnectionToHostImpl::set_candidate_config(
scoped_ptr<CandidateSessionConfig> config) {
DCHECK_EQ(state_, INITIALIZING);
candidate_config_ = config.Pass();
}
-
-const SessionConfig& ConnectionToHost::config() {
+const SessionConfig& ConnectionToHostImpl::config() {
return session_->config();
}
-ClipboardStub* ConnectionToHost::clipboard_forwarder() {
+ClipboardStub* ConnectionToHostImpl::clipboard_forwarder() {
return &clipboard_forwarder_;
}
-HostStub* ConnectionToHost::host_stub() {
+HostStub* ConnectionToHostImpl::host_stub() {
// TODO(wez): Add a HostFilter class, equivalent to input filter.
return control_dispatcher_.get();
}
-InputStub* ConnectionToHost::input_stub() {
+InputStub* ConnectionToHostImpl::input_stub() {
return &event_forwarder_;
}
-void ConnectionToHost::set_client_stub(ClientStub* client_stub) {
+void ConnectionToHostImpl::set_client_stub(ClientStub* client_stub) {
client_stub_ = client_stub;
}
-void ConnectionToHost::set_clipboard_stub(ClipboardStub* clipboard_stub) {
+void ConnectionToHostImpl::set_clipboard_stub(ClipboardStub* clipboard_stub) {
clipboard_stub_ = clipboard_stub;
}
-void ConnectionToHost::set_video_stub(VideoStub* video_stub) {
+void ConnectionToHostImpl::set_video_stub(VideoStub* video_stub) {
DCHECK(video_stub);
monitored_video_stub_.reset(new MonitoredVideoStub(
- video_stub,
- base::TimeDelta::FromSeconds(
- MonitoredVideoStub::kConnectivityCheckDelaySeconds),
- base::Bind(&ConnectionToHost::OnVideoChannelStatus,
+ video_stub, base::TimeDelta::FromSeconds(
+ MonitoredVideoStub::kConnectivityCheckDelaySeconds),
+ base::Bind(&ConnectionToHostImpl::OnVideoChannelStatus,
base::Unretained(this))));
}
-void ConnectionToHost::set_audio_stub(AudioStub* audio_stub) {
+void ConnectionToHostImpl::set_audio_stub(AudioStub* audio_stub) {
audio_stub_ = audio_stub;
}
-void ConnectionToHost::OnSignalStrategyStateChange(
+void ConnectionToHostImpl::OnSignalStrategyStateChange(
SignalStrategy::State state) {
DCHECK(CalledOnValidThread());
DCHECK(event_callback_);
@@ -144,21 +143,21 @@ void ConnectionToHost::OnSignalStrategyStateChange(
}
}
-bool ConnectionToHost::OnSignalStrategyIncomingStanza(
- const buzz::XmlElement* stanza) {
+bool ConnectionToHostImpl::OnSignalStrategyIncomingStanza(
+ const buzz::XmlElement* stanza) {
return false;
}
-void ConnectionToHost::OnSessionManagerReady() {
+void ConnectionToHostImpl::OnSessionManagerReady() {
DCHECK(CalledOnValidThread());
// After SessionManager is initialized we can try to connect to the host.
- session_ = session_manager_->Connect(
- host_jid_, authenticator_.Pass(), candidate_config_.Pass());
+ session_ = session_manager_->Connect(host_jid_, authenticator_.Pass(),
+ candidate_config_.Pass());
session_->SetEventHandler(this);
}
-void ConnectionToHost::OnIncomingSession(
+void ConnectionToHostImpl::OnIncomingSession(
Session* session,
SessionManager::IncomingSessionResponse* response) {
DCHECK(CalledOnValidThread());
@@ -166,8 +165,7 @@ void ConnectionToHost::OnIncomingSession(
*response = SessionManager::DECLINE;
}
-void ConnectionToHost::OnSessionStateChange(
- Session::State state) {
+void ConnectionToHostImpl::OnSessionStateChange(Session::State state) {
DCHECK(CalledOnValidThread());
DCHECK(event_callback_);
@@ -229,17 +227,17 @@ void ConnectionToHost::OnSessionStateChange(
}
}
-void ConnectionToHost::OnSessionRouteChange(const std::string& channel_name,
- const TransportRoute& route) {
+void ConnectionToHostImpl::OnSessionRouteChange(const std::string& channel_name,
+ const TransportRoute& route) {
event_callback_->OnRouteChanged(channel_name, route);
}
-void ConnectionToHost::OnChannelInitialized(
+void ConnectionToHostImpl::OnChannelInitialized(
ChannelDispatcherBase* channel_dispatcher) {
NotifyIfChannelsReady();
}
-void ConnectionToHost::OnChannelError(
+void ConnectionToHostImpl::OnChannelError(
ChannelDispatcherBase* channel_dispatcher,
ErrorCode error) {
LOG(ERROR) << "Failed to connect channel " << channel_dispatcher;
@@ -247,15 +245,15 @@ void ConnectionToHost::OnChannelError(
return;
}
-void ConnectionToHost::OnVideoChannelStatus(bool active) {
+void ConnectionToHostImpl::OnVideoChannelStatus(bool active) {
event_callback_->OnConnectionReady(active);
}
-ConnectionToHost::State ConnectionToHost::state() const {
+ConnectionToHost::State ConnectionToHostImpl::state() const {
return state_;
}
-void ConnectionToHost::NotifyIfChannelsReady() {
+void ConnectionToHostImpl::NotifyIfChannelsReady() {
if (!control_dispatcher_.get() || !control_dispatcher_->is_connected())
return;
if (!event_dispatcher_.get() || !event_dispatcher_->is_connected())
@@ -275,12 +273,12 @@ void ConnectionToHost::NotifyIfChannelsReady() {
SetState(CONNECTED, OK);
}
-void ConnectionToHost::CloseOnError(ErrorCode error) {
+void ConnectionToHostImpl::CloseOnError(ErrorCode error) {
CloseChannels();
SetState(FAILED, error);
}
-void ConnectionToHost::CloseChannels() {
+void ConnectionToHostImpl::CloseChannels() {
control_dispatcher_.reset();
event_dispatcher_.reset();
clipboard_forwarder_.set_clipboard_stub(nullptr);
@@ -289,7 +287,7 @@ void ConnectionToHost::CloseChannels() {
audio_reader_.reset();
}
-void ConnectionToHost::SetState(State state, ErrorCode error) {
+void ConnectionToHostImpl::SetState(State state, ErrorCode error) {
DCHECK(CalledOnValidThread());
// |error| should be specified only when |state| is set to FAILED.
DCHECK(state == FAILED || error == OK);
diff --git a/remoting/protocol/connection_to_host_impl.h b/remoting/protocol/connection_to_host_impl.h
new file mode 100644
index 0000000..fc2306d
--- /dev/null
+++ b/remoting/protocol/connection_to_host_impl.h
@@ -0,0 +1,136 @@
+// Copyright 2015 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_PROTOCOL_CONNECTION_TO_HOST_IMPL_H_
+#define REMOTING_PROTOCOL_CONNECTION_TO_HOST_IMPL_H_
+
+#include <set>
+#include <string>
+
+#include "base/callback_forward.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/non_thread_safe.h"
+#include "remoting/proto/internal.pb.h"
+#include "remoting/protocol/channel_dispatcher_base.h"
+#include "remoting/protocol/clipboard_filter.h"
+#include "remoting/protocol/connection_to_host.h"
+#include "remoting/protocol/errors.h"
+#include "remoting/protocol/input_filter.h"
+#include "remoting/protocol/message_reader.h"
+#include "remoting/protocol/monitored_video_stub.h"
+#include "remoting/protocol/session.h"
+#include "remoting/protocol/session_config.h"
+#include "remoting/protocol/session_manager.h"
+#include "remoting/signaling/signal_strategy.h"
+
+namespace remoting {
+
+class XmppProxy;
+class VideoPacket;
+
+namespace protocol {
+
+class AudioReader;
+class ClientControlDispatcher;
+class ClientEventDispatcher;
+class ClientVideoDispatcher;
+
+class ConnectionToHostImpl : public ConnectionToHost,
+ public SignalStrategy::Listener,
+ public SessionManager::Listener,
+ public Session::EventHandler,
+ public ChannelDispatcherBase::EventHandler,
+ public base::NonThreadSafe {
+ public:
+ ConnectionToHostImpl();
+ ~ConnectionToHostImpl() override;
+
+ // ConnectionToHost interface.
+ void set_candidate_config(scoped_ptr<CandidateSessionConfig> config) override;
+ void set_client_stub(ClientStub* client_stub) override;
+ void set_clipboard_stub(ClipboardStub* clipboard_stub) override;
+ void set_video_stub(VideoStub* video_stub) override;
+ void set_audio_stub(AudioStub* audio_stub) override;
+ void Connect(SignalStrategy* signal_strategy,
+ scoped_ptr<TransportFactory> transport_factory,
+ scoped_ptr<Authenticator> authenticator,
+ const std::string& host_jid,
+ HostEventCallback* event_callback) override;
+ const SessionConfig& config() override;
+ ClipboardStub* clipboard_forwarder() override;
+ HostStub* host_stub() override;
+ InputStub* input_stub() override;
+ State state() const override;
+
+ private:
+ // SignalStrategy::StatusObserver interface.
+ void OnSignalStrategyStateChange(SignalStrategy::State state) override;
+ bool OnSignalStrategyIncomingStanza(const buzz::XmlElement* stanza) override;
+
+ // SessionManager::Listener interface.
+ void OnSessionManagerReady() override;
+ void OnIncomingSession(
+ Session* session,
+ SessionManager::IncomingSessionResponse* response) override;
+
+ // Session::EventHandler interface.
+ void OnSessionStateChange(Session::State state) override;
+ void OnSessionRouteChange(const std::string& channel_name,
+ const TransportRoute& route) override;
+
+ // ChannelDispatcherBase::EventHandler interface.
+ void OnChannelInitialized(ChannelDispatcherBase* channel_dispatcher) override;
+ void OnChannelError(ChannelDispatcherBase* channel_dispatcher,
+ ErrorCode error) override;
+
+ // MonitoredVideoStub::EventHandler interface.
+ virtual void OnVideoChannelStatus(bool active);
+
+ void NotifyIfChannelsReady();
+
+ void CloseOnError(ErrorCode error);
+
+ // Stops writing in the channels.
+ void CloseChannels();
+
+ void SetState(State state, ErrorCode error);
+
+ std::string host_jid_;
+ std::string host_public_key_;
+ scoped_ptr<Authenticator> authenticator_;
+
+ HostEventCallback* event_callback_;
+
+ scoped_ptr<CandidateSessionConfig> candidate_config_;
+
+ // Stub for incoming messages.
+ ClientStub* client_stub_;
+ ClipboardStub* clipboard_stub_;
+ AudioStub* audio_stub_;
+
+ SignalStrategy* signal_strategy_;
+ scoped_ptr<SessionManager> session_manager_;
+ scoped_ptr<Session> session_;
+ scoped_ptr<MonitoredVideoStub> monitored_video_stub_;
+
+ scoped_ptr<ClientVideoDispatcher> video_dispatcher_;
+ scoped_ptr<AudioReader> audio_reader_;
+ scoped_ptr<ClientControlDispatcher> control_dispatcher_;
+ scoped_ptr<ClientEventDispatcher> event_dispatcher_;
+ ClipboardFilter clipboard_forwarder_;
+ InputFilter event_forwarder_;
+
+ // Internal state of the connection.
+ State state_;
+ ErrorCode error_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ConnectionToHostImpl);
+};
+
+} // namespace protocol
+} // namespace remoting
+
+#endif // REMOTING_PROTOCOL_CONNECTION_TO_HOST_IMPL_H_
diff --git a/remoting/protocol/fake_connection_to_host.cc b/remoting/protocol/fake_connection_to_host.cc
new file mode 100644
index 0000000..025f720
--- /dev/null
+++ b/remoting/protocol/fake_connection_to_host.cc
@@ -0,0 +1,118 @@
+// Copyright 2015 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/protocol/fake_connection_to_host.h"
+
+#include "remoting/protocol/authenticator.h"
+
+namespace remoting {
+namespace test {
+
+FakeConnectionToHost::FakeConnectionToHost()
+ : state_(INITIALIZING),
+ session_config_(protocol::SessionConfig::ForTest()) {
+}
+
+FakeConnectionToHost::~FakeConnectionToHost() {
+}
+
+void FakeConnectionToHost::set_candidate_config(
+ scoped_ptr<protocol::CandidateSessionConfig> config) {
+}
+
+void FakeConnectionToHost::set_client_stub(protocol::ClientStub* client_stub) {
+}
+
+void FakeConnectionToHost::set_clipboard_stub(
+ protocol::ClipboardStub* clipboard_stub) {
+}
+
+void FakeConnectionToHost::set_video_stub(protocol::VideoStub* video_stub) {
+}
+
+void FakeConnectionToHost::set_audio_stub(protocol::AudioStub* audio_stub) {
+}
+
+void FakeConnectionToHost::Connect(
+ SignalStrategy* signal_strategy,
+ scoped_ptr<protocol::TransportFactory> transport_factory,
+ scoped_ptr<protocol::Authenticator> authenticator,
+ const std::string& host_jid,
+ HostEventCallback* event_callback) {
+ DCHECK(event_callback);
+
+ event_callback_ = event_callback;
+
+ SetState(CONNECTING, protocol::OK);
+}
+
+void FakeConnectionToHost::SignalStateChange(protocol::Session::State state,
+ protocol::ErrorCode error) {
+ DCHECK(event_callback_);
+
+ switch (state) {
+ case protocol::Session::INITIALIZING:
+ case protocol::Session::CONNECTING:
+ case protocol::Session::ACCEPTING:
+ case protocol::Session::AUTHENTICATING:
+ // No updates for these events.
+ break;
+
+ case protocol::Session::CONNECTED:
+ SetState(CONNECTED, error);
+ break;
+
+ case protocol::Session::AUTHENTICATED:
+ SetState(AUTHENTICATED, error);
+ break;
+
+ case protocol::Session::CLOSED:
+ SetState(CLOSED, error);
+ break;
+
+ case protocol::Session::FAILED:
+ DCHECK(error != protocol::ErrorCode::OK);
+ SetState(FAILED, error);
+ break;
+ }
+}
+
+void FakeConnectionToHost::SignalConnectionReady(bool ready) {
+ DCHECK(event_callback_);
+
+ event_callback_->OnConnectionReady(ready);
+}
+
+const protocol::SessionConfig& FakeConnectionToHost::config() {
+ return session_config_;
+}
+
+protocol::ClipboardStub* FakeConnectionToHost::clipboard_forwarder() {
+ return &mock_clipboard_stub_;
+}
+
+protocol::HostStub* FakeConnectionToHost::host_stub() {
+ return &mock_host_stub_;
+}
+
+protocol::InputStub* FakeConnectionToHost::input_stub() {
+ return &mock_input_stub_;
+}
+
+protocol::ConnectionToHost::State FakeConnectionToHost::state() const {
+ return state_;
+}
+
+void FakeConnectionToHost::SetState(State state, protocol::ErrorCode error) {
+ // |error| should be specified only when |state| is set to FAILED.
+ DCHECK(state == FAILED || error == protocol::OK);
+
+ if (state != state_) {
+ state_ = state;
+ event_callback_->OnConnectionState(state_, error);
+ }
+}
+
+} // namespace test
+} // namespace remoting
diff --git a/remoting/protocol/fake_connection_to_host.h b/remoting/protocol/fake_connection_to_host.h
new file mode 100644
index 0000000..8220a96
--- /dev/null
+++ b/remoting/protocol/fake_connection_to_host.h
@@ -0,0 +1,65 @@
+// Copyright 2015 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_PROTOCOL_FAKE_CONNECTION_TO_HOST_H_
+#define REMOTING_PROTOCOL_FAKE_CONNECTION_TO_HOST_H_
+
+#include <string>
+
+#include "remoting/protocol/connection_to_host.h"
+#include "remoting/protocol/protocol_mock_objects.h"
+
+namespace remoting {
+namespace test {
+
+class FakeConnectionToHost : public protocol::ConnectionToHost {
+ public:
+ FakeConnectionToHost();
+ ~FakeConnectionToHost() override;
+
+ // ConnectionToHost interface.
+ void set_candidate_config(
+ scoped_ptr<protocol::CandidateSessionConfig> config) override;
+ void set_client_stub(protocol::ClientStub* client_stub) override;
+ void set_clipboard_stub(protocol::ClipboardStub* clipboard_stub) override;
+ void set_video_stub(protocol::VideoStub* video_stub) override;
+ void set_audio_stub(protocol::AudioStub* audio_stub) override;
+ void Connect(SignalStrategy* signal_strategy,
+ scoped_ptr<protocol::TransportFactory> transport_factory,
+ scoped_ptr<protocol::Authenticator> authenticator,
+ const std::string& host_jid,
+ HostEventCallback* event_callback) override;
+ const protocol::SessionConfig& config() override;
+ protocol::ClipboardStub* clipboard_forwarder() override;
+ protocol::HostStub* host_stub() override;
+ protocol::InputStub* input_stub() override;
+ State state() const override;
+
+ // Calls OnConnectionState on the |event_callback_| with the supplied state
+ // and error.
+ void SignalStateChange(protocol::Session::State state,
+ protocol::ErrorCode error);
+
+ // Calls OnConnectionReady on the |event_callback_| with the supplied bool.
+ void SignalConnectionReady(bool ready);
+
+ private:
+ void SetState(State state, protocol::ErrorCode error);
+
+ State state_;
+
+ HostEventCallback* event_callback_;
+
+ testing::NiceMock<protocol::MockClipboardStub> mock_clipboard_stub_;
+ testing::NiceMock<protocol::MockHostStub> mock_host_stub_;
+ testing::NiceMock<protocol::MockInputStub> mock_input_stub_;
+ protocol::SessionConfig session_config_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeConnectionToHost);
+};
+
+} // namespace test
+} // namespace remoting
+
+#endif // REMOTING_PROTOCOL_FAKE_CONNECTION_TO_HOST_H_
diff --git a/remoting/protocol/protocol_mock_objects.h b/remoting/protocol/protocol_mock_objects.h
index 758151f..2484e9a 100644
--- a/remoting/protocol/protocol_mock_objects.h
+++ b/remoting/protocol/protocol_mock_objects.h
@@ -32,9 +32,8 @@ namespace protocol {
class MockConnectionToClient : public ConnectionToClient {
public:
- MockConnectionToClient(Session* session,
- HostStub* host_stub);
- virtual ~MockConnectionToClient();
+ MockConnectionToClient(Session* session, HostStub* host_stub);
+ ~MockConnectionToClient() override;
MOCK_METHOD1(Init, void(Session* session));
MOCK_METHOD0(video_stub, VideoStub*());
@@ -69,24 +68,25 @@ class MockConnectionToClient : public ConnectionToClient {
DISALLOW_COPY_AND_ASSIGN(MockConnectionToClient);
};
-class MockConnectionToClientEventHandler :
- public ConnectionToClient::EventHandler {
+class MockConnectionToClientEventHandler
+ : public ConnectionToClient::EventHandler {
public:
MockConnectionToClientEventHandler();
- virtual ~MockConnectionToClientEventHandler();
+ ~MockConnectionToClientEventHandler() override;
MOCK_METHOD1(OnConnectionAuthenticating,
void(ConnectionToClient* connection));
MOCK_METHOD1(OnConnectionAuthenticated, void(ConnectionToClient* connection));
MOCK_METHOD1(OnConnectionChannelsConnected,
void(ConnectionToClient* connection));
- MOCK_METHOD2(OnConnectionClosed, void(ConnectionToClient* connection,
- ErrorCode error));
+ MOCK_METHOD2(OnConnectionClosed,
+ void(ConnectionToClient* connection, ErrorCode error));
MOCK_METHOD2(OnEventTimestamp,
void(ConnectionToClient* connection, int64 timestamp));
- MOCK_METHOD3(OnRouteChange, void(ConnectionToClient* connection,
- const std::string& channel_name,
- const TransportRoute& route));
+ MOCK_METHOD3(OnRouteChange,
+ void(ConnectionToClient* connection,
+ const std::string& channel_name,
+ const TransportRoute& route));
private:
DISALLOW_COPY_AND_ASSIGN(MockConnectionToClientEventHandler);
@@ -95,7 +95,7 @@ class MockConnectionToClientEventHandler :
class MockClipboardStub : public ClipboardStub {
public:
MockClipboardStub();
- virtual ~MockClipboardStub();
+ ~MockClipboardStub() override;
MOCK_METHOD1(InjectClipboardEvent, void(const ClipboardEvent& event));
@@ -118,7 +118,7 @@ class MockCursorShapeChangeCallback {
class MockInputStub : public InputStub {
public:
MockInputStub();
- virtual ~MockInputStub();
+ ~MockInputStub() override;
MOCK_METHOD1(InjectKeyEvent, void(const KeyEvent& event));
MOCK_METHOD1(InjectTextEvent, void(const TextEvent& event));
@@ -132,15 +132,14 @@ class MockInputStub : public InputStub {
class MockHostStub : public HostStub {
public:
MockHostStub();
- virtual ~MockHostStub();
+ ~MockHostStub() override;
MOCK_METHOD1(NotifyClientResolution,
void(const ClientResolution& resolution));
MOCK_METHOD1(ControlVideo, void(const VideoControl& video_control));
MOCK_METHOD1(ControlAudio, void(const AudioControl& audio_control));
MOCK_METHOD1(SetCapabilities, void(const Capabilities& capabilities));
- MOCK_METHOD1(RequestPairing,
- void(const PairingRequest& pairing_request));
+ MOCK_METHOD1(RequestPairing, void(const PairingRequest& pairing_request));
MOCK_METHOD1(DeliverClientMessage, void(const ExtensionMessage& message));
private:
@@ -150,7 +149,7 @@ class MockHostStub : public HostStub {
class MockClientStub : public ClientStub {
public:
MockClientStub();
- virtual ~MockClientStub();
+ ~MockClientStub() override;
// ClientStub mock implementation.
MOCK_METHOD1(SetCapabilities, void(const Capabilities& capabilities));
@@ -171,7 +170,7 @@ class MockClientStub : public ClientStub {
class MockCursorShapeStub : public CursorShapeStub {
public:
MockCursorShapeStub();
- virtual ~MockCursorShapeStub();
+ ~MockCursorShapeStub() override;
MOCK_METHOD1(SetCursorShape, void(const CursorShapeInfo& cursor_shape));
@@ -182,12 +181,13 @@ class MockCursorShapeStub : public CursorShapeStub {
class MockVideoStub : public VideoStub {
public:
MockVideoStub();
- virtual ~MockVideoStub();
+ ~MockVideoStub() override;
- MOCK_METHOD2(ProcessVideoPacketPtr, void(const VideoPacket* video_packet,
- const base::Closure& done));
- virtual void ProcessVideoPacket(scoped_ptr<VideoPacket> video_packet,
- const base::Closure& done) {
+ MOCK_METHOD2(ProcessVideoPacketPtr,
+ void(const VideoPacket* video_packet,
+ const base::Closure& done));
+ void ProcessVideoPacket(scoped_ptr<VideoPacket> video_packet,
+ const base::Closure& done) override {
ProcessVideoPacketPtr(video_packet.get(), done);
}
@@ -198,7 +198,7 @@ class MockVideoStub : public VideoStub {
class MockSession : public Session {
public:
MockSession();
- virtual ~MockSession();
+ ~MockSession() override;
MOCK_METHOD1(SetEventHandler, void(Session::EventHandler* event_handler));
MOCK_METHOD0(error, ErrorCode());
@@ -223,25 +223,25 @@ class MockSession : public Session {
class MockSessionManager : public SessionManager {
public:
MockSessionManager();
- virtual ~MockSessionManager();
+ ~MockSessionManager() override;
MOCK_METHOD2(Init, void(SignalStrategy*, Listener*));
- MOCK_METHOD3(ConnectPtr, Session*(
- const std::string& host_jid,
- Authenticator* authenticator,
- CandidateSessionConfig* config));
+ MOCK_METHOD3(ConnectPtr,
+ Session*(const std::string& host_jid,
+ Authenticator* authenticator,
+ CandidateSessionConfig* config));
MOCK_METHOD0(Close, void());
MOCK_METHOD1(set_authenticator_factory_ptr,
void(AuthenticatorFactory* factory));
- virtual scoped_ptr<Session> Connect(
+ scoped_ptr<Session> Connect(
const std::string& host_jid,
scoped_ptr<Authenticator> authenticator,
- scoped_ptr<CandidateSessionConfig> config) {
+ scoped_ptr<CandidateSessionConfig> config) override {
return make_scoped_ptr(
ConnectPtr(host_jid, authenticator.get(), config.get()));
}
- virtual void set_authenticator_factory(
- scoped_ptr<AuthenticatorFactory> authenticator_factory) {
+ void set_authenticator_factory(
+ scoped_ptr<AuthenticatorFactory> authenticator_factory) override {
set_authenticator_factory_ptr(authenticator_factory.release());
}
diff --git a/remoting/remoting_srcs.gypi b/remoting/remoting_srcs.gypi
index 1248808a..68994c0 100644
--- a/remoting/remoting_srcs.gypi
+++ b/remoting/remoting_srcs.gypi
@@ -109,8 +109,9 @@
'protocol/clipboard_thread_proxy.h',
'protocol/connection_to_client.cc',
'protocol/connection_to_client.h',
- 'protocol/connection_to_host.cc',
'protocol/connection_to_host.h',
+ 'protocol/connection_to_host_impl.cc',
+ 'protocol/connection_to_host_impl.h',
'protocol/content_description.cc',
'protocol/content_description.h',
'protocol/datagram_channel_factory.h',
diff --git a/remoting/remoting_test.gypi b/remoting/remoting_test.gypi
index f0ac015..467cbfe 100644
--- a/remoting/remoting_test.gypi
+++ b/remoting/remoting_test.gypi
@@ -31,6 +31,8 @@
'host/fake_mouse_cursor_monitor.h',
'protocol/fake_authenticator.cc',
'protocol/fake_authenticator.h',
+ 'protocol/fake_connection_to_host.cc',
+ 'protocol/fake_connection_to_host.h',
'protocol/fake_datagram_socket.cc',
'protocol/fake_datagram_socket.h',
'protocol/fake_session.cc',
@@ -45,8 +47,11 @@
'signaling/mock_signal_strategy.cc',
'signaling/mock_signal_strategy.h',
'test/access_token_fetcher.cc',
+ 'test/access_token_fetcher.h',
'test/app_remoting_test_driver_environment.cc',
+ 'test/app_remoting_test_driver_environment.h',
'test/fake_access_token_fetcher.cc',
+ 'test/fake_access_token_fetcher.h',
'test/fake_network_dispatcher.cc',
'test/fake_network_dispatcher.h',
'test/fake_network_manager.cc',
@@ -54,14 +59,24 @@
'test/fake_port_allocator.cc',
'test/fake_port_allocator.h',
'test/fake_remote_host_info_fetcher.cc',
+ 'test/fake_remote_host_info_fetcher.h',
'test/fake_socket_factory.cc',
'test/fake_socket_factory.h',
'test/leaky_bucket.cc',
'test/leaky_bucket.h',
'test/mock_access_token_fetcher.cc',
+ 'test/mock_access_token_fetcher.h',
'test/refresh_token_store.cc',
+ 'test/refresh_token_store.h',
+ 'test/remote_connection_observer.h',
'test/remote_host_info.cc',
+ 'test/remote_host_info.h',
'test/remote_host_info_fetcher.cc',
+ 'test/remote_host_info_fetcher.h',
+ 'test/test_chromoting_client.cc',
+ 'test/test_chromoting_client.h',
+ 'test/test_video_renderer.cc',
+ 'test/test_video_renderer.h',
],
'conditions': [
['enable_remoting_host == 0', {
@@ -243,6 +258,7 @@
'test/access_token_fetcher_unittest.cc',
'test/app_remoting_test_driver_environment_unittest.cc',
'test/remote_host_info_fetcher_unittest.cc',
+ 'test/test_chromoting_client_unittest.cc',
],
'conditions': [
[ 'OS=="win"', {
diff --git a/remoting/test/access_token_fetcher_unittest.cc b/remoting/test/access_token_fetcher_unittest.cc
index b061512..6ab9c82 100644
--- a/remoting/test/access_token_fetcher_unittest.cc
+++ b/remoting/test/access_token_fetcher_unittest.cc
@@ -56,36 +56,21 @@ namespace test {
// necessary, for use by the AccessTokenFetcher.
class AccessTokenFetcherTest : public ::testing::Test {
public:
- AccessTokenFetcherTest() :
- url_fetcher_factory_(nullptr) {}
- ~AccessTokenFetcherTest() override {}
-
- void OnAccessTokenRetrieved(
- base::Closure done_closure,
- const std::string& access_token,
- const std::string& refresh_token) {
- access_token_retrieved_ = access_token;
- refresh_token_retrieved_ = refresh_token;
-
- done_closure.Run();
- }
+ AccessTokenFetcherTest();
+ ~AccessTokenFetcherTest() override;
+
+ void OnAccessTokenRetrieved(base::Closure done_closure,
+ const std::string& access_token,
+ const std::string& refresh_token);
protected:
// Test interface.
- void SetUp() override {
- if (!base::MessageLoop::current()) {
- // Create a temporary message loop if the current thread does not already
- // have one so we can use its task runner to create a request object.
- message_loop_.reset(new base::MessageLoopForIO);
- }
- }
+ void SetUp() override;
void SetFakeResponse(const GURL& url,
const std::string& data,
net::HttpStatusCode code,
- net::URLRequestStatus::Status status) {
- url_fetcher_factory_.SetFakeResponse(url, data, code, status);
- }
+ net::URLRequestStatus::Status status);
// Used for result verification
std::string access_token_retrieved_;
@@ -98,29 +83,56 @@ class AccessTokenFetcherTest : public ::testing::Test {
DISALLOW_COPY_AND_ASSIGN(AccessTokenFetcherTest);
};
+AccessTokenFetcherTest::AccessTokenFetcherTest()
+ : url_fetcher_factory_(nullptr) {
+}
+
+AccessTokenFetcherTest::~AccessTokenFetcherTest() {
+}
+
+void AccessTokenFetcherTest::OnAccessTokenRetrieved(
+ base::Closure done_closure,
+ const std::string& access_token,
+ const std::string& refresh_token) {
+ access_token_retrieved_ = access_token;
+ refresh_token_retrieved_ = refresh_token;
+
+ done_closure.Run();
+}
+
+void AccessTokenFetcherTest::SetUp() {
+ if (!base::MessageLoop::current()) {
+ // Create a temporary message loop if the current thread does not already
+ // have one so we can use its task runner to create a request object.
+ message_loop_.reset(new base::MessageLoopForIO);
+ }
+}
+
+void AccessTokenFetcherTest::SetFakeResponse(
+ const GURL& url,
+ const std::string& data,
+ net::HttpStatusCode code,
+ net::URLRequestStatus::Status status) {
+ url_fetcher_factory_.SetFakeResponse(url, data, code, status);
+}
+
TEST_F(AccessTokenFetcherTest, ExchangeAuthCodeForAccessToken) {
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_url(),
- kAuthCodeExchangeValidResponse,
- net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
-
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_info_url(),
- kValidTokenInfoResponse,
- net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ kAuthCodeExchangeValidResponse, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
+
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_info_url(),
+ kValidTokenInfoResponse, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
base::RunLoop run_loop;
AccessTokenCallback access_token_callback =
base::Bind(&AccessTokenFetcherTest::OnAccessTokenRetrieved,
- base::Unretained(this),
- run_loop.QuitClosure());
+ base::Unretained(this), run_loop.QuitClosure());
AccessTokenFetcher access_token_fetcher;
- access_token_fetcher.GetAccessTokenFromAuthCode(
- kAuthCodeValue,
- access_token_callback);
+ access_token_fetcher.GetAccessTokenFromAuthCode(kAuthCodeValue,
+ access_token_callback);
run_loop.Run();
@@ -129,28 +141,22 @@ TEST_F(AccessTokenFetcherTest, ExchangeAuthCodeForAccessToken) {
}
TEST_F(AccessTokenFetcherTest, ExchangeRefreshTokenForAccessToken) {
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_url(),
- kRefreshTokenExchangeValidResponse,
- net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
-
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_info_url(),
- kValidTokenInfoResponse,
- net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ kRefreshTokenExchangeValidResponse, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
+
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_info_url(),
+ kValidTokenInfoResponse, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
base::RunLoop run_loop;
AccessTokenCallback access_token_callback =
base::Bind(&AccessTokenFetcherTest::OnAccessTokenRetrieved,
- base::Unretained(this),
- run_loop.QuitClosure());
+ base::Unretained(this), run_loop.QuitClosure());
AccessTokenFetcher access_token_fetcher;
- access_token_fetcher.GetAccessTokenFromRefreshToken(
- kRefreshTokenValue,
- access_token_callback);
+ access_token_fetcher.GetAccessTokenFromRefreshToken(kRefreshTokenValue,
+ access_token_callback);
run_loop.Run();
@@ -159,29 +165,23 @@ TEST_F(AccessTokenFetcherTest, ExchangeRefreshTokenForAccessToken) {
}
TEST_F(AccessTokenFetcherTest, MultipleAccessTokenCalls) {
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_url(),
- kAuthCodeExchangeValidResponse,
- net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
-
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_info_url(),
- kValidTokenInfoResponse,
- net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ kAuthCodeExchangeValidResponse, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
+
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_info_url(),
+ kValidTokenInfoResponse, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
scoped_ptr<base::RunLoop> run_loop;
run_loop.reset(new base::RunLoop());
AccessTokenCallback access_token_callback =
base::Bind(&AccessTokenFetcherTest::OnAccessTokenRetrieved,
- base::Unretained(this),
- run_loop->QuitClosure());
+ base::Unretained(this), run_loop->QuitClosure());
AccessTokenFetcher access_token_fetcher;
- access_token_fetcher.GetAccessTokenFromAuthCode(
- kAuthCodeValue,
- access_token_callback);
+ access_token_fetcher.GetAccessTokenFromAuthCode(kAuthCodeValue,
+ access_token_callback);
run_loop->Run();
@@ -193,21 +193,17 @@ TEST_F(AccessTokenFetcherTest, MultipleAccessTokenCalls) {
refresh_token_retrieved_.clear();
// Update the response since we will call the refresh token method next.
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_url(),
- kRefreshTokenExchangeValidResponse,
- net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ kRefreshTokenExchangeValidResponse, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
run_loop.reset(new base::RunLoop());
access_token_callback =
base::Bind(&AccessTokenFetcherTest::OnAccessTokenRetrieved,
- base::Unretained(this),
- run_loop->QuitClosure());
+ base::Unretained(this), run_loop->QuitClosure());
- access_token_fetcher.GetAccessTokenFromRefreshToken(
- kRefreshTokenValue,
- access_token_callback);
+ access_token_fetcher.GetAccessTokenFromRefreshToken(kRefreshTokenValue,
+ access_token_callback);
run_loop->Run();
@@ -217,16 +213,14 @@ TEST_F(AccessTokenFetcherTest, MultipleAccessTokenCalls) {
run_loop.reset(new base::RunLoop());
access_token_callback =
base::Bind(&AccessTokenFetcherTest::OnAccessTokenRetrieved,
- base::Unretained(this),
- run_loop->QuitClosure());
+ base::Unretained(this), run_loop->QuitClosure());
// Reset our token data for the next iteration.
access_token_retrieved_.clear();
refresh_token_retrieved_.clear();
- access_token_fetcher.GetAccessTokenFromRefreshToken(
- kRefreshTokenValue,
- access_token_callback);
+ access_token_fetcher.GetAccessTokenFromRefreshToken(kRefreshTokenValue,
+ access_token_callback);
run_loop->Run();
@@ -235,22 +229,18 @@ TEST_F(AccessTokenFetcherTest, MultipleAccessTokenCalls) {
}
TEST_F(AccessTokenFetcherTest, ExchangeAuthCode_Unauthorized_Error) {
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_url(),
- kAuthCodeExchangeValidResponse,
- net::HTTP_UNAUTHORIZED,
- net::URLRequestStatus::FAILED);
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ kAuthCodeExchangeValidResponse, net::HTTP_UNAUTHORIZED,
+ net::URLRequestStatus::FAILED);
base::RunLoop run_loop;
AccessTokenCallback access_token_callback =
base::Bind(&AccessTokenFetcherTest::OnAccessTokenRetrieved,
- base::Unretained(this),
- run_loop.QuitClosure());
+ base::Unretained(this), run_loop.QuitClosure());
AccessTokenFetcher access_token_fetcher;
- access_token_fetcher.GetAccessTokenFromAuthCode(
- kAuthCodeValue,
- access_token_callback);
+ access_token_fetcher.GetAccessTokenFromAuthCode(kAuthCodeValue,
+ access_token_callback);
run_loop.Run();
@@ -260,22 +250,18 @@ TEST_F(AccessTokenFetcherTest, ExchangeAuthCode_Unauthorized_Error) {
}
TEST_F(AccessTokenFetcherTest, ExchangeRefreshToken_Unauthorized_Error) {
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_url(),
- kRefreshTokenExchangeValidResponse,
- net::HTTP_UNAUTHORIZED,
- net::URLRequestStatus::FAILED);
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ kRefreshTokenExchangeValidResponse, net::HTTP_UNAUTHORIZED,
+ net::URLRequestStatus::FAILED);
base::RunLoop run_loop;
AccessTokenCallback access_token_callback =
base::Bind(&AccessTokenFetcherTest::OnAccessTokenRetrieved,
- base::Unretained(this),
- run_loop.QuitClosure());
+ base::Unretained(this), run_loop.QuitClosure());
AccessTokenFetcher access_token_fetcher;
- access_token_fetcher.GetAccessTokenFromRefreshToken(
- kRefreshTokenValue,
- access_token_callback);
+ access_token_fetcher.GetAccessTokenFromRefreshToken(kRefreshTokenValue,
+ access_token_callback);
run_loop.Run();
@@ -285,22 +271,18 @@ TEST_F(AccessTokenFetcherTest, ExchangeRefreshToken_Unauthorized_Error) {
}
TEST_F(AccessTokenFetcherTest, ExchangeAuthCode_NetworkError) {
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_url(),
- kAuthCodeExchangeValidResponse,
- net::HTTP_NOT_FOUND,
- net::URLRequestStatus::FAILED);
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ kAuthCodeExchangeValidResponse, net::HTTP_NOT_FOUND,
+ net::URLRequestStatus::FAILED);
base::RunLoop run_loop;
AccessTokenCallback access_token_callback =
base::Bind(&AccessTokenFetcherTest::OnAccessTokenRetrieved,
- base::Unretained(this),
- run_loop.QuitClosure());
+ base::Unretained(this), run_loop.QuitClosure());
AccessTokenFetcher access_token_fetcher;
- access_token_fetcher.GetAccessTokenFromAuthCode(
- kAuthCodeValue,
- access_token_callback);
+ access_token_fetcher.GetAccessTokenFromAuthCode(kAuthCodeValue,
+ access_token_callback);
run_loop.Run();
@@ -310,22 +292,18 @@ TEST_F(AccessTokenFetcherTest, ExchangeAuthCode_NetworkError) {
}
TEST_F(AccessTokenFetcherTest, ExchangeRefreshToken_NetworkError) {
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_url(),
- kRefreshTokenExchangeValidResponse,
- net::HTTP_NOT_FOUND,
- net::URLRequestStatus::FAILED);
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ kRefreshTokenExchangeValidResponse, net::HTTP_NOT_FOUND,
+ net::URLRequestStatus::FAILED);
base::RunLoop run_loop;
AccessTokenCallback access_token_callback =
base::Bind(&AccessTokenFetcherTest::OnAccessTokenRetrieved,
- base::Unretained(this),
- run_loop.QuitClosure());
+ base::Unretained(this), run_loop.QuitClosure());
AccessTokenFetcher access_token_fetcher;
- access_token_fetcher.GetAccessTokenFromRefreshToken(
- kRefreshTokenValue,
- access_token_callback);
+ access_token_fetcher.GetAccessTokenFromRefreshToken(kRefreshTokenValue,
+ access_token_callback);
run_loop.Run();
@@ -335,28 +313,22 @@ TEST_F(AccessTokenFetcherTest, ExchangeRefreshToken_NetworkError) {
}
TEST_F(AccessTokenFetcherTest, AuthCode_GetTokenInfoResponse_InvalidToken) {
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_url(),
- kAuthCodeExchangeValidResponse,
- net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
-
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_info_url(),
- kInvalidTokenInfoResponse,
- net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ kAuthCodeExchangeValidResponse, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
+
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_info_url(),
+ kInvalidTokenInfoResponse, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
base::RunLoop run_loop;
AccessTokenCallback access_token_callback =
base::Bind(&AccessTokenFetcherTest::OnAccessTokenRetrieved,
- base::Unretained(this),
- run_loop.QuitClosure());
+ base::Unretained(this), run_loop.QuitClosure());
AccessTokenFetcher access_token_fetcher;
- access_token_fetcher.GetAccessTokenFromAuthCode(
- kAuthCodeValue,
- access_token_callback);
+ access_token_fetcher.GetAccessTokenFromAuthCode(kAuthCodeValue,
+ access_token_callback);
run_loop.Run();
@@ -366,22 +338,18 @@ TEST_F(AccessTokenFetcherTest, AuthCode_GetTokenInfoResponse_InvalidToken) {
}
TEST_F(AccessTokenFetcherTest, ExchangeAuthCodeForAccessToken_EmptyToken) {
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_url(),
- kAuthCodeExchangeEmptyResponse,
- net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ kAuthCodeExchangeEmptyResponse, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
base::RunLoop run_loop;
AccessTokenCallback access_token_callback =
base::Bind(&AccessTokenFetcherTest::OnAccessTokenRetrieved,
- base::Unretained(this),
- run_loop.QuitClosure());
+ base::Unretained(this), run_loop.QuitClosure());
AccessTokenFetcher access_token_fetcher;
- access_token_fetcher.GetAccessTokenFromAuthCode(
- kAuthCodeValue,
- access_token_callback);
+ access_token_fetcher.GetAccessTokenFromAuthCode(kAuthCodeValue,
+ access_token_callback);
run_loop.Run();
@@ -391,28 +359,22 @@ TEST_F(AccessTokenFetcherTest, ExchangeAuthCodeForAccessToken_EmptyToken) {
}
TEST_F(AccessTokenFetcherTest, RefreshToken_GetTokenInfoResponse_InvalidToken) {
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_url(),
- kRefreshTokenExchangeValidResponse,
- net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
-
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_info_url(),
- kInvalidTokenInfoResponse,
- net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ kRefreshTokenExchangeValidResponse, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
+
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_info_url(),
+ kInvalidTokenInfoResponse, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
base::RunLoop run_loop;
AccessTokenCallback access_token_callback =
base::Bind(&AccessTokenFetcherTest::OnAccessTokenRetrieved,
- base::Unretained(this),
- run_loop.QuitClosure());
+ base::Unretained(this), run_loop.QuitClosure());
AccessTokenFetcher access_token_fetcher;
- access_token_fetcher.GetAccessTokenFromRefreshToken(
- kRefreshTokenValue,
- access_token_callback);
+ access_token_fetcher.GetAccessTokenFromRefreshToken(kRefreshTokenValue,
+ access_token_callback);
run_loop.Run();
@@ -422,22 +384,18 @@ TEST_F(AccessTokenFetcherTest, RefreshToken_GetTokenInfoResponse_InvalidToken) {
}
TEST_F(AccessTokenFetcherTest, ExchangeRefreshTokenForAccessToken_EmptyToken) {
- SetFakeResponse(
- GaiaUrls::GetInstance()->oauth2_token_url(),
- kRefreshTokenExchangeEmptyResponse,
- net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ kRefreshTokenExchangeEmptyResponse, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
base::RunLoop run_loop;
AccessTokenCallback access_token_callback =
base::Bind(&AccessTokenFetcherTest::OnAccessTokenRetrieved,
- base::Unretained(this),
- run_loop.QuitClosure());
+ base::Unretained(this), run_loop.QuitClosure());
AccessTokenFetcher access_token_fetcher;
- access_token_fetcher.GetAccessTokenFromRefreshToken(
- kRefreshTokenValue,
- access_token_callback);
+ access_token_fetcher.GetAccessTokenFromRefreshToken(kRefreshTokenValue,
+ access_token_callback);
run_loop.Run();
diff --git a/remoting/test/remote_connection_observer.h b/remoting/test/remote_connection_observer.h
new file mode 100644
index 0000000..99da8be
--- /dev/null
+++ b/remoting/test/remote_connection_observer.h
@@ -0,0 +1,57 @@
+// Copyright 2015 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_TEST_REMOTE_CONNECTION_OBSERVER_H_
+#define REMOTING_TEST_REMOTE_CONNECTION_OBSERVER_H_
+
+#include <string>
+
+#include "remoting/proto/control.pb.h"
+#include "remoting/protocol/connection_to_host.h"
+#include "remoting/protocol/errors.h"
+#include "remoting/protocol/transport.h"
+
+namespace remoting {
+namespace test {
+
+// Interface for a remote connection observer which will be notified when
+// certain connection status changes occur or events from the remote host
+// are received. Observers must not tear-down the object they have registered
+// while in a callback. The callbacks should be used for informational
+// purposes only.
+class RemoteConnectionObserver {
+ public:
+ RemoteConnectionObserver() {}
+ virtual ~RemoteConnectionObserver() {}
+
+ // Called when the connection state has changed.
+ virtual void ConnectionStateChanged(protocol::ConnectionToHost::State state,
+ protocol::ErrorCode error_code) {}
+
+ // Called when the connection is ready to be used, |ready| will be true once
+ // the video channel has been established.
+ virtual void ConnectionReady(bool ready) {}
+
+ // Called when a channel changes the type of route it is using.
+ virtual void RouteChanged(const std::string& channel_name,
+ const protocol::TransportRoute& route) {}
+
+ // Called when the host sends its list of capabilities to the client.
+ virtual void CapabilitiesSet(const std::string& capabilities) {}
+
+ // Called when a pairing response has been set.
+ virtual void PairingResponseSet(
+ const protocol::PairingResponse& pairing_response) {}
+
+ // Called when we have received an ExtensionMessage from the host.
+ virtual void HostMessageReceived(const protocol::ExtensionMessage& message) {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RemoteConnectionObserver);
+};
+
+} // namespace test
+} // namespace remoting
+
+#endif // REMOTING_TEST_REMOTE_CONNECTION_OBSERVER_H_
diff --git a/remoting/test/test_chromoting_client.cc b/remoting/test/test_chromoting_client.cc
new file mode 100644
index 0000000..925a4fb
--- /dev/null
+++ b/remoting/test/test_chromoting_client.cc
@@ -0,0 +1,340 @@
+// Copyright 2015 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/test/test_chromoting_client.h"
+
+#include <string>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/thread_task_runner_handle.h"
+#include "jingle/glue/thread_wrapper.h"
+#include "net/base/request_priority.h"
+#include "net/socket/client_socket_factory.h"
+#include "remoting/base/url_request_context_getter.h"
+#include "remoting/client/audio_player.h"
+#include "remoting/client/chromoting_client.h"
+#include "remoting/client/client_context.h"
+#include "remoting/client/token_fetcher_proxy.h"
+#include "remoting/protocol/authentication_method.h"
+#include "remoting/protocol/chromium_port_allocator.h"
+#include "remoting/protocol/host_stub.h"
+#include "remoting/protocol/libjingle_transport_factory.h"
+#include "remoting/protocol/negotiating_client_authenticator.h"
+#include "remoting/protocol/network_settings.h"
+#include "remoting/protocol/session_config.h"
+#include "remoting/protocol/third_party_client_authenticator.h"
+#include "remoting/signaling/xmpp_signal_strategy.h"
+#include "remoting/test/remote_host_info_fetcher.h"
+#include "remoting/test/test_video_renderer.h"
+
+namespace {
+
+const char kXmppHostName[] = "talk.google.com";
+const int kXmppPortNumber = 5222;
+
+// Used as the TokenFetcherCallback for App Remoting sessions.
+void FetchThirdPartyToken(
+ const std::string& authorization_token,
+ const std::string& shared_secret,
+ const GURL& token_url,
+ const std::string& host_public_key,
+ const std::string& scope,
+ base::WeakPtr<remoting::TokenFetcherProxy> token_fetcher_proxy) {
+ DVLOG(1) << "FetchThirdPartyToken("
+ << "token_url: " << token_url << ", "
+ << "host_public_key: " << host_public_key << ", "
+ << "scope: " << scope << ") Called";
+
+ if (token_fetcher_proxy) {
+ token_fetcher_proxy->OnTokenFetched(authorization_token, shared_secret);
+ token_fetcher_proxy.reset();
+ } else {
+ LOG(ERROR) << "Invalid token fetcher proxy passed in";
+ }
+}
+
+const char* ConnectionStateToFriendlyString(
+ remoting::protocol::ConnectionToHost::State state) {
+ switch (state) {
+ case remoting::protocol::ConnectionToHost::INITIALIZING:
+ return "INITIALIZING";
+
+ case remoting::protocol::ConnectionToHost::CONNECTING:
+ return "CONNECTING";
+
+ case remoting::protocol::ConnectionToHost::AUTHENTICATED:
+ return "AUTHENTICATED";
+
+ case remoting::protocol::ConnectionToHost::CONNECTED:
+ return "CONNECTED";
+
+ case remoting::protocol::ConnectionToHost::CLOSED:
+ return "CLOSED";
+
+ case remoting::protocol::ConnectionToHost::FAILED:
+ return "FAILED";
+
+ default:
+ LOG(ERROR) << "Unknown connection state: '" << state << "'";
+ return "UNKNOWN";
+ }
+}
+
+const char* ProtocolErrorToFriendlyString(
+ remoting::protocol::ErrorCode error_code) {
+ switch (error_code) {
+ case remoting::protocol::OK:
+ return "NONE";
+
+ case remoting::protocol::PEER_IS_OFFLINE:
+ return "PEER_IS_OFFLINE";
+
+ case remoting::protocol::SESSION_REJECTED:
+ return "SESSION_REJECTED";
+
+ case remoting::protocol::AUTHENTICATION_FAILED:
+ return "AUTHENTICATION_FAILED";
+
+ case remoting::protocol::INCOMPATIBLE_PROTOCOL:
+ return "INCOMPATIBLE_PROTOCOL";
+
+ case remoting::protocol::HOST_OVERLOAD:
+ return "HOST_OVERLOAD";
+
+ case remoting::protocol::CHANNEL_CONNECTION_ERROR:
+ return "CHANNEL_CONNECTION_ERROR";
+
+ case remoting::protocol::SIGNALING_ERROR:
+ return "SIGNALING_ERROR";
+
+ case remoting::protocol::SIGNALING_TIMEOUT:
+ return "SIGNALING_TIMEOUT";
+
+ case remoting::protocol::UNKNOWN_ERROR:
+ return "UNKNOWN_ERROR";
+
+ default:
+ LOG(ERROR) << "Unrecognized error code: '" << error_code << "'";
+ return "UNKNOWN_ERROR";
+ }
+}
+
+} // namespace
+
+namespace remoting {
+namespace test {
+
+TestChromotingClient::TestChromotingClient()
+ : connection_to_host_state_(protocol::ConnectionToHost::INITIALIZING),
+ connection_error_code_(protocol::OK) {
+}
+
+TestChromotingClient::~TestChromotingClient() {
+ // Ensure any connections are closed and the members are destroyed in the
+ // appropriate order.
+ EndConnection();
+}
+
+void TestChromotingClient::StartConnection(
+ const std::string& user_name,
+ const std::string& access_token,
+ const RemoteHostInfo& remote_host_info) {
+ DCHECK(!user_name.empty());
+ DCHECK(!access_token.empty());
+ DCHECK(remote_host_info.IsReadyForConnection());
+
+ // Required to establish a connection to the host.
+ jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
+
+ scoped_refptr<URLRequestContextGetter> request_context_getter;
+ request_context_getter = new URLRequestContextGetter(
+ base::ThreadTaskRunnerHandle::Get(), // network_runner
+ base::ThreadTaskRunnerHandle::Get()); // file_runner
+
+ client_context_.reset(new ClientContext(base::ThreadTaskRunnerHandle::Get()));
+
+ video_renderer_.reset(new TestVideoRenderer());
+
+ chromoting_client_.reset(new ChromotingClient(client_context_.get(),
+ this, // client_user_interface.
+ video_renderer_.get(),
+ nullptr // audio_player
+ ));
+
+ if (test_connection_to_host_) {
+ chromoting_client_->SetConnectionToHostForTests(
+ test_connection_to_host_.Pass());
+ }
+
+ XmppSignalStrategy::XmppServerConfig xmpp_server_config;
+ xmpp_server_config.host = kXmppHostName;
+ xmpp_server_config.port = kXmppPortNumber;
+ xmpp_server_config.use_tls = true;
+ xmpp_server_config.username = user_name;
+ xmpp_server_config.auth_token = access_token;
+
+ // Set up the signal strategy. This must outlive the client object.
+ signal_strategy_.reset(
+ new XmppSignalStrategy(net::ClientSocketFactory::GetDefaultFactory(),
+ request_context_getter, xmpp_server_config));
+
+ protocol::NetworkSettings network_settings(
+ protocol::NetworkSettings::NAT_TRAVERSAL_FULL);
+
+ scoped_ptr<protocol::ChromiumPortAllocator> port_allocator(
+ protocol::ChromiumPortAllocator::Create(request_context_getter,
+ network_settings));
+
+ scoped_ptr<protocol::TransportFactory> transport_factory(
+ new protocol::LibjingleTransportFactory(
+ signal_strategy_.get(), port_allocator.Pass(), network_settings));
+
+ scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>
+ token_fetcher(new TokenFetcherProxy(
+ base::Bind(&FetchThirdPartyToken, remote_host_info.authorization_code,
+ remote_host_info.shared_secret),
+ "FAKE_HOST_PUBLIC_KEY"));
+
+ std::vector<protocol::AuthenticationMethod> auth_methods;
+ auth_methods.push_back(protocol::AuthenticationMethod::ThirdParty());
+
+ // FetchSecretCallback is used for PIN based auth which we aren't using so we
+ // can pass a null callback here.
+ protocol::FetchSecretCallback fetch_secret_callback;
+ scoped_ptr<protocol::Authenticator> authenticator(
+ new protocol::NegotiatingClientAuthenticator(
+ std::string(), // client_pairing_id
+ std::string(), // shared_secret
+ std::string(), // authentication_tag
+ fetch_secret_callback, token_fetcher.Pass(), auth_methods));
+
+ chromoting_client_->Start(signal_strategy_.get(), authenticator.Pass(),
+ transport_factory.Pass(), remote_host_info.host_jid,
+ std::string() // capabilities
+ );
+}
+
+void TestChromotingClient::EndConnection() {
+ // Clearing out the client will close the connection.
+ chromoting_client_.reset();
+
+ // The signal strategy object must outlive the client so destroy it next.
+ signal_strategy_.reset();
+
+ // The connection state will be updated when the chromoting client was
+ // destroyed if an active connection was established, but not in other cases.
+ // We should be consistent in either case so we will set the state if needed.
+ if (connection_to_host_state_ != protocol::ConnectionToHost::CLOSED &&
+ connection_to_host_state_ != protocol::ConnectionToHost::FAILED &&
+ connection_error_code_ == protocol::OK) {
+ OnConnectionState(protocol::ConnectionToHost::CLOSED, protocol::OK);
+ }
+}
+
+void TestChromotingClient::AddRemoteConnectionObserver(
+ RemoteConnectionObserver* observer) {
+ DCHECK(observer);
+
+ connection_observers_.AddObserver(observer);
+}
+
+void TestChromotingClient::RemoveRemoteConnectionObserver(
+ RemoteConnectionObserver* observer) {
+ DCHECK(observer);
+
+ connection_observers_.RemoveObserver(observer);
+}
+
+void TestChromotingClient::SetConnectionToHostForTests(
+ scoped_ptr<protocol::ConnectionToHost> connection_to_host) {
+ test_connection_to_host_ = connection_to_host.Pass();
+}
+
+void TestChromotingClient::OnConnectionState(
+ protocol::ConnectionToHost::State state,
+ protocol::ErrorCode error_code) {
+ DVLOG(1) << "TestChromotingClient::OnConnectionState("
+ << "state: " << ConnectionStateToFriendlyString(state) << ", "
+ << "error_code: " << ProtocolErrorToFriendlyString(error_code)
+ << ") Called";
+
+ connection_error_code_ = error_code;
+ connection_to_host_state_ = state;
+
+ FOR_EACH_OBSERVER(RemoteConnectionObserver, connection_observers_,
+ ConnectionStateChanged(state, error_code));
+}
+
+void TestChromotingClient::OnConnectionReady(bool ready) {
+ DVLOG(1) << "TestChromotingClient::OnConnectionReady("
+ << "ready:" << ready << ") Called";
+
+ FOR_EACH_OBSERVER(RemoteConnectionObserver, connection_observers_,
+ ConnectionReady(ready));
+}
+
+void TestChromotingClient::OnRouteChanged(
+ const std::string& channel_name,
+ const protocol::TransportRoute& route) {
+ DVLOG(1) << "TestChromotingClient::OnRouteChanged("
+ << "channel_name:" << channel_name << ", "
+ << "route:" << protocol::TransportRoute::GetTypeString(route.type)
+ << ") Called";
+
+ FOR_EACH_OBSERVER(RemoteConnectionObserver, connection_observers_,
+ RouteChanged(channel_name, route));
+}
+
+void TestChromotingClient::SetCapabilities(const std::string& capabilities) {
+ DVLOG(1) << "TestChromotingClient::SetCapabilities("
+ << "capabilities: " << capabilities << ") Called";
+
+ FOR_EACH_OBSERVER(RemoteConnectionObserver, connection_observers_,
+ CapabilitiesSet(capabilities));
+}
+
+void TestChromotingClient::SetPairingResponse(
+ const protocol::PairingResponse& pairing_response) {
+ DVLOG(1) << "TestChromotingClient::SetPairingResponse("
+ << "client_id: " << pairing_response.client_id() << ", "
+ << "shared_secret: " << pairing_response.shared_secret()
+ << ") Called";
+
+ FOR_EACH_OBSERVER(RemoteConnectionObserver, connection_observers_,
+ PairingResponseSet(pairing_response));
+}
+
+void TestChromotingClient::DeliverHostMessage(
+ const protocol::ExtensionMessage& message) {
+ DVLOG(1) << "TestChromotingClient::DeliverHostMessage("
+ << "type: " << message.type() << ", "
+ << "data: " << message.data() << ") Called";
+
+ FOR_EACH_OBSERVER(RemoteConnectionObserver, connection_observers_,
+ HostMessageReceived(message));
+}
+
+protocol::ClipboardStub* TestChromotingClient::GetClipboardStub() {
+ DVLOG(1) << "TestChromotingClient::GetClipboardStub() Called";
+ return this;
+}
+
+protocol::CursorShapeStub* TestChromotingClient::GetCursorShapeStub() {
+ DVLOG(1) << "TestChromotingClient::GetCursorShapeStub() Called";
+ return this;
+}
+
+void TestChromotingClient::InjectClipboardEvent(
+ const protocol::ClipboardEvent& event) {
+ DVLOG(1) << "TestChromotingClient::InjectClipboardEvent() Called";
+}
+
+void TestChromotingClient::SetCursorShape(
+ const protocol::CursorShapeInfo& cursor_shape) {
+ DVLOG(1) << "TestChromotingClient::SetCursorShape() Called";
+}
+
+} // namespace test
+} // namespace remoting
diff --git a/remoting/test/test_chromoting_client.h b/remoting/test/test_chromoting_client.h
new file mode 100644
index 0000000..6899df0
--- /dev/null
+++ b/remoting/test/test_chromoting_client.h
@@ -0,0 +1,113 @@
+// Copyright 2015 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_TEST_TEST_CHROMOTING_CLIENT_H_
+#define REMOTING_TEST_TEST_CHROMOTING_CLIENT_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
+#include "remoting/client/client_user_interface.h"
+#include "remoting/protocol/clipboard_filter.h"
+#include "remoting/protocol/cursor_shape_stub.h"
+#include "remoting/test/remote_connection_observer.h"
+#include "remoting/test/remote_host_info.h"
+
+namespace remoting {
+class ChromotingClient;
+class ClientContext;
+class XmppSignalStrategy;
+class VideoRenderer;
+}
+
+namespace remoting {
+namespace test {
+
+// Manages a chromoting connection to a remote host. Destroying a
+// TestChromotingClient object with an active connection will close it.
+// Must be used from a thread running an IO message loop.
+// RemoteConnectionObserver objects must not destroy this class within a
+// callback.
+class TestChromotingClient : public ClientUserInterface,
+ public protocol::ClipboardStub,
+ public protocol::CursorShapeStub {
+ public:
+ TestChromotingClient();
+ ~TestChromotingClient() override;
+
+ // Starts a chromoting connection with the specified remote host.
+ void StartConnection(const std::string& user_name,
+ const std::string& access_token,
+ const RemoteHostInfo& remote_host_info);
+
+ // Ends the current remote connection and updates the connection state.
+ void EndConnection();
+
+ // Registers an observer which will be notfied when remote connection events
+ // occur. Registered Observers must not tear-down this object on receipt of
+ // these callbacks. The callbacks should be used for informational purposes.
+ void AddRemoteConnectionObserver(RemoteConnectionObserver* observer);
+
+ // Unregisters an observerer from notifications for remote connection events.
+ void RemoveRemoteConnectionObserver(RemoteConnectionObserver* observer);
+
+ // Used to set a fake/mock connection object for TestChromotingClient tests.
+ void SetConnectionToHostForTests(
+ scoped_ptr<protocol::ConnectionToHost> connection_to_host);
+
+ private:
+ // ClientUserInterface interface.
+ void OnConnectionState(protocol::ConnectionToHost::State state,
+ protocol::ErrorCode error_code) override;
+ void OnConnectionReady(bool ready) override;
+ void OnRouteChanged(const std::string& channel_name,
+ const protocol::TransportRoute& route) override;
+ void SetCapabilities(const std::string& capabilities) override;
+ void SetPairingResponse(
+ const protocol::PairingResponse& pairing_response) override;
+ void DeliverHostMessage(const protocol::ExtensionMessage& message) override;
+ protocol::ClipboardStub* GetClipboardStub() override;
+ protocol::CursorShapeStub* GetCursorShapeStub() override;
+
+ // protocol::ClipboardStub interface.
+ void InjectClipboardEvent(const protocol::ClipboardEvent& event) override;
+
+ // protocol::CursorShapeStub interface.
+ void SetCursorShape(const protocol::CursorShapeInfo& cursor_shape) override;
+
+ // Tracks the current connection state.
+ protocol::ConnectionToHost::State connection_to_host_state_;
+
+ // Tracks the most recent connection error code seen.
+ protocol::ErrorCode connection_error_code_;
+
+ // List of observers which are notified when remote connection events occur.
+ // We specify true below for the 'check_empty' flag so the list will check to
+ // see if all observers have been unregistered when it is destroyed.
+ ObserverList<RemoteConnectionObserver, true> connection_observers_;
+
+ // ConnectionToHost used by TestChromotingClient tests.
+ scoped_ptr<protocol::ConnectionToHost> test_connection_to_host_;
+
+ // Creates and manages the connection to the remote host.
+ scoped_ptr<ChromotingClient> chromoting_client_;
+
+ // Manages the threads and task runners for |chromoting_client_|.
+ scoped_ptr<ClientContext> client_context_;
+
+ // Processes video packets from the host.
+ scoped_ptr<VideoRenderer> video_renderer_;
+
+ // Used to establish an XMPP connection with the google talk service.
+ scoped_ptr<XmppSignalStrategy> signal_strategy_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestChromotingClient);
+};
+
+} // namespace test
+} // namespace remoting
+
+#endif // REMOTING_TEST_TEST_CHROMOTING_CLIENT_H_
diff --git a/remoting/test/test_chromoting_client_unittest.cc b/remoting/test/test_chromoting_client_unittest.cc
new file mode 100644
index 0000000..9f23289
--- /dev/null
+++ b/remoting/test/test_chromoting_client_unittest.cc
@@ -0,0 +1,211 @@
+// Copyright 2015 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 <string>
+
+#include "base/message_loop/message_loop.h"
+#include "remoting/protocol/fake_connection_to_host.h"
+#include "remoting/test/test_chromoting_client.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+const char kTestUserName[] = "test_user@faux_address.com";
+const char kAccessToken[] = "faux_access_token";
+}
+
+namespace remoting {
+namespace test {
+
+using testing::_;
+
+// Provides base functionality for the TestChromotingClient Tests below. This
+// fixture also creates an IO MessageLoop for use by the TestChromotingClient.
+// Overrides a subset of the RemoteConnectionObserver interface to track
+// connection status changes for result verification.
+class TestChromotingClientTest : public ::testing::Test,
+ public RemoteConnectionObserver {
+ public:
+ TestChromotingClientTest();
+ ~TestChromotingClientTest() override;
+
+ protected:
+ // testing::Test interface.
+ void SetUp() override;
+ void TearDown() override;
+
+ // Used for result verification.
+ bool is_connected_to_host_;
+ protocol::ConnectionToHost::State connection_state_;
+ protocol::ErrorCode error_code_;
+
+ // Used for simulating different conditions for the TestChromotingClient.
+ RemoteHostInfo remote_host_info_;
+ FakeConnectionToHost* fake_connection_to_host_;
+
+ scoped_ptr<TestChromotingClient> test_chromoting_client_;
+
+ private:
+ // RemoteConnectionObserver interface.
+ void ConnectionStateChanged(protocol::ConnectionToHost::State state,
+ protocol::ErrorCode error_code) override;
+ void ConnectionReady(bool ready) override;
+
+ base::MessageLoopForIO message_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestChromotingClientTest);
+};
+
+TestChromotingClientTest::TestChromotingClientTest()
+ : is_connected_to_host_(false),
+ connection_state_(protocol::ConnectionToHost::INITIALIZING),
+ error_code_(protocol::OK),
+ fake_connection_to_host_(nullptr) {
+}
+
+TestChromotingClientTest::~TestChromotingClientTest() {
+}
+
+void TestChromotingClientTest::SetUp() {
+ test_chromoting_client_.reset(new TestChromotingClient());
+ test_chromoting_client_->AddRemoteConnectionObserver(this);
+
+ // Pass ownership of the FakeConnectionToHost to the chromoting instance but
+ // keep the ptr around so we can use it to simulate state changes. It will
+ // remain valid until |test_chromoting_client_| is destroyed.
+ fake_connection_to_host_ = new FakeConnectionToHost();
+ test_chromoting_client_->SetConnectionToHostForTests(
+ make_scoped_ptr(fake_connection_to_host_));
+
+ remote_host_info_.remote_host_status = kRemoteHostStatusReady;
+}
+
+void TestChromotingClientTest::TearDown() {
+ test_chromoting_client_->RemoveRemoteConnectionObserver(this);
+ fake_connection_to_host_ = nullptr;
+
+ // The chromoting instance must be destroyed before the message loop.
+ test_chromoting_client_.reset();
+
+ // The LibjingleTransportFactory destroys the PortAllocator via a DeleteSoon
+ // operation. If we do not allow the message loop to run here, we run the
+ // risk of the DeleteSoon task being dropped and incurring a memory leak.
+ message_loop_.RunUntilIdle();
+}
+
+void TestChromotingClientTest::ConnectionStateChanged(
+ protocol::ConnectionToHost::State state,
+ protocol::ErrorCode error_code) {
+ connection_state_ = state;
+ error_code_ = error_code;
+
+ if (state != protocol::ConnectionToHost::State::CONNECTED ||
+ error_code != protocol::OK) {
+ is_connected_to_host_ = false;
+ }
+}
+
+void TestChromotingClientTest::ConnectionReady(bool ready) {
+ if (ready) {
+ is_connected_to_host_ = true;
+ }
+}
+
+TEST_F(TestChromotingClientTest, StartConnectionAndDisconnect) {
+ test_chromoting_client_->StartConnection(kTestUserName, kAccessToken,
+ remote_host_info_);
+ EXPECT_EQ(protocol::ConnectionToHost::State::CONNECTING, connection_state_);
+ EXPECT_EQ(protocol::OK, error_code_);
+ EXPECT_FALSE(is_connected_to_host_);
+
+ // Simulate an AUTHENTICATED message being sent from the Jingle session.
+ fake_connection_to_host_->SignalStateChange(protocol::Session::AUTHENTICATED,
+ protocol::OK);
+ EXPECT_EQ(protocol::ConnectionToHost::State::AUTHENTICATED,
+ connection_state_);
+ EXPECT_EQ(protocol::OK, error_code_);
+ EXPECT_FALSE(is_connected_to_host_);
+
+ // Simulate a CONNECTED message being sent from the Jingle session.
+ fake_connection_to_host_->SignalStateChange(protocol::Session::CONNECTED,
+ protocol::OK);
+ EXPECT_EQ(protocol::ConnectionToHost::State::CONNECTED, connection_state_);
+ EXPECT_EQ(protocol::OK, error_code_);
+ EXPECT_FALSE(is_connected_to_host_);
+
+ fake_connection_to_host_->SignalConnectionReady(true);
+ EXPECT_EQ(protocol::ConnectionToHost::State::CONNECTED, connection_state_);
+ EXPECT_EQ(protocol::OK, error_code_);
+ EXPECT_TRUE(is_connected_to_host_);
+
+ test_chromoting_client_->EndConnection();
+ EXPECT_EQ(protocol::ConnectionToHost::State::CLOSED, connection_state_);
+ EXPECT_EQ(protocol::OK, error_code_);
+ EXPECT_FALSE(is_connected_to_host_);
+}
+
+TEST_F(TestChromotingClientTest,
+ StartConnectionThenFailWithAuthenticationError) {
+ test_chromoting_client_->StartConnection(kTestUserName, kAccessToken,
+ remote_host_info_);
+ EXPECT_EQ(protocol::ConnectionToHost::State::CONNECTING, connection_state_);
+ EXPECT_EQ(protocol::OK, error_code_);
+ EXPECT_FALSE(is_connected_to_host_);
+
+ fake_connection_to_host_->SignalStateChange(protocol::Session::FAILED,
+ protocol::AUTHENTICATION_FAILED);
+ EXPECT_EQ(protocol::ConnectionToHost::State::FAILED, connection_state_);
+ EXPECT_EQ(protocol::ErrorCode::AUTHENTICATION_FAILED, error_code_);
+ EXPECT_FALSE(is_connected_to_host_);
+
+ // Close the connection via the TestChromotingClient and verify the error
+ // state is persisted.
+ test_chromoting_client_->EndConnection();
+ EXPECT_EQ(protocol::ConnectionToHost::State::FAILED, connection_state_);
+ EXPECT_EQ(protocol::ErrorCode::AUTHENTICATION_FAILED, error_code_);
+ EXPECT_FALSE(is_connected_to_host_);
+}
+
+TEST_F(TestChromotingClientTest, StartConnectionThenFailWithUnknownError) {
+ test_chromoting_client_->StartConnection(kTestUserName, kAccessToken,
+ remote_host_info_);
+ EXPECT_EQ(protocol::ConnectionToHost::State::CONNECTING, connection_state_);
+ EXPECT_EQ(protocol::OK, error_code_);
+ EXPECT_FALSE(is_connected_to_host_);
+
+ // Simulate an AUTHENTICATED message being sent from the Jingle session.
+ fake_connection_to_host_->SignalStateChange(protocol::Session::AUTHENTICATED,
+ protocol::OK);
+ EXPECT_EQ(protocol::ConnectionToHost::State::AUTHENTICATED,
+ connection_state_);
+ EXPECT_EQ(protocol::OK, error_code_);
+ EXPECT_FALSE(is_connected_to_host_);
+
+ // Simulate a CONNECTED message being sent from the Jingle session.
+ fake_connection_to_host_->SignalStateChange(protocol::Session::CONNECTED,
+ protocol::OK);
+ EXPECT_EQ(protocol::ConnectionToHost::State::CONNECTED, connection_state_);
+ EXPECT_EQ(protocol::OK, error_code_);
+ EXPECT_FALSE(is_connected_to_host_);
+
+ fake_connection_to_host_->SignalConnectionReady(true);
+ EXPECT_EQ(protocol::ConnectionToHost::State::CONNECTED, connection_state_);
+ EXPECT_EQ(protocol::OK, error_code_);
+ EXPECT_TRUE(is_connected_to_host_);
+
+ fake_connection_to_host_->SignalStateChange(protocol::Session::FAILED,
+ protocol::UNKNOWN_ERROR);
+ EXPECT_EQ(protocol::ConnectionToHost::State::FAILED, connection_state_);
+ EXPECT_EQ(protocol::ErrorCode::UNKNOWN_ERROR, error_code_);
+ EXPECT_FALSE(is_connected_to_host_);
+
+ // Close the connection via the TestChromotingClient and verify the error
+ // state is persisted.
+ test_chromoting_client_->EndConnection();
+ EXPECT_EQ(protocol::ConnectionToHost::State::FAILED, connection_state_);
+ EXPECT_EQ(protocol::ErrorCode::UNKNOWN_ERROR, error_code_);
+ EXPECT_FALSE(is_connected_to_host_);
+}
+
+} // namespace test
+} // namespace remoting
diff --git a/remoting/test/test_video_renderer.cc b/remoting/test/test_video_renderer.cc
new file mode 100644
index 0000000..864356a
--- /dev/null
+++ b/remoting/test/test_video_renderer.cc
@@ -0,0 +1,49 @@
+// Copyright 2015 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/test/test_video_renderer.h"
+
+#include "base/logging.h"
+#include "remoting/proto/video.pb.h"
+
+namespace remoting {
+namespace test {
+
+TestVideoRenderer::TestVideoRenderer() : video_frames_processed_(0) {
+}
+
+TestVideoRenderer::~TestVideoRenderer() {
+}
+
+void TestVideoRenderer::OnSessionConfig(const protocol::SessionConfig& config) {
+ DVLOG(2) << "TestVideoRenderer::OnSessionConfig() Called";
+}
+
+ChromotingStats* TestVideoRenderer::GetStats() {
+ DVLOG(2) << "TestVideoRenderer::GetStats() Called";
+ return nullptr;
+}
+
+protocol::VideoStub* TestVideoRenderer::GetVideoStub() {
+ DVLOG(2) << "TestVideoRenderer::GetVideoStub() Called";
+ return this;
+}
+
+void TestVideoRenderer::ProcessVideoPacket(scoped_ptr<VideoPacket> video_packet,
+ const base::Closure& done) {
+ if (!video_packet->data().empty()) {
+ // If the video frame was not a keep alive frame (i.e. not empty) then
+ // count it.
+ DVLOG(2) << "Video Packet Processed, Total: " << ++video_frames_processed_;
+ } else {
+ // Log at a high verbosity level as we receive empty packets frequently and
+ // they can clutter up the debug output if the level is set too low.
+ DVLOG(3) << "Empty Video Packet received.";
+ }
+
+ done.Run();
+}
+
+} // namespace test
+} // namespace remoting
diff --git a/remoting/test/test_video_renderer.h b/remoting/test/test_video_renderer.h
new file mode 100644
index 0000000..fcf122a
--- /dev/null
+++ b/remoting/test/test_video_renderer.h
@@ -0,0 +1,41 @@
+// Copyright 2015 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_TEST_TEST_VIDEO_RENDERER_H_
+#define REMOTING_TEST_TEST_VIDEO_RENDERER_H_
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "remoting/client/video_renderer.h"
+#include "remoting/protocol/video_stub.h"
+
+namespace remoting {
+namespace test {
+
+// Processes video packets as they are received from the remote host.
+class TestVideoRenderer : public VideoRenderer, public protocol::VideoStub {
+ public:
+ TestVideoRenderer();
+ ~TestVideoRenderer() override;
+
+ // VideoRenderer interface.
+ void OnSessionConfig(const protocol::SessionConfig& config) override;
+ ChromotingStats* GetStats() override;
+ protocol::VideoStub* GetVideoStub() override;
+
+ private:
+ // protocol::VideoStub interface.
+ void ProcessVideoPacket(scoped_ptr<VideoPacket> video_packet,
+ const base::Closure& done) override;
+
+ // Track the number of populated video frames which have been received.
+ int video_frames_processed_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestVideoRenderer);
+};
+
+} // namespace test
+} // namespace remoting
+
+#endif // REMOTING_TEST_TEST_VIDEO_RENDERER_H_