summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--remoting/client/chromoting_client.cc85
-rw-r--r--remoting/client/chromoting_client.h14
-rw-r--r--remoting/client/chromoting_view.h12
-rw-r--r--remoting/client/plugin/chromoting_instance.cc12
-rw-r--r--remoting/client/plugin/chromoting_scriptable_object.cc42
-rw-r--r--remoting/client/plugin/chromoting_scriptable_object.h59
-rw-r--r--remoting/client/plugin/pepper_view.cc59
-rw-r--r--remoting/client/plugin/pepper_view.h8
-rw-r--r--remoting/client/plugin/pepper_view_proxy.cc8
-rw-r--r--remoting/client/plugin/pepper_view_proxy.h4
-rw-r--r--remoting/protocol/connection_to_host.cc74
-rw-r--r--remoting/protocol/connection_to_host.h33
-rw-r--r--remoting/protocol/session.h4
13 files changed, 225 insertions, 189 deletions
diff --git a/remoting/client/chromoting_client.cc b/remoting/client/chromoting_client.cc
index 71a611a..22569625 100644
--- a/remoting/client/chromoting_client.cc
+++ b/remoting/client/chromoting_client.cc
@@ -5,7 +5,6 @@
#include "remoting/client/chromoting_client.h"
#include "base/bind.h"
-#include "jingle/glue/thread_wrapper.h"
#include "remoting/client/chromoting_view.h"
#include "remoting/client/client_context.h"
#include "remoting/client/input_handler.h"
@@ -29,23 +28,16 @@ ChromotingClient::ChromotingClient(const ClientConfig& config,
rectangle_decoder_(rectangle_decoder),
input_handler_(input_handler),
client_done_(client_done),
- state_(CREATED),
packet_being_processed_(false),
- last_sequence_number_(0) {
+ last_sequence_number_(0),
+ thread_proxy_(context_->network_message_loop()) {
}
ChromotingClient::~ChromotingClient() {
}
void ChromotingClient::Start(scoped_refptr<XmppProxy> xmpp_proxy) {
- if (!message_loop()->BelongsToCurrentThread()) {
- message_loop()->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &ChromotingClient::Start, xmpp_proxy));
- return;
- }
-
- jingle_glue::JingleThreadWrapper::EnsureForCurrentThread();
+ DCHECK(message_loop()->BelongsToCurrentThread());
connection_->Connect(xmpp_proxy, config_.local_jid, config_.host_jid,
config_.host_public_key, config_.access_code,
@@ -85,25 +77,13 @@ ChromotingStats* ChromotingClient::GetStats() {
}
void ChromotingClient::Repaint() {
- if (!message_loop()->BelongsToCurrentThread()) {
- message_loop()->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &ChromotingClient::Repaint));
- return;
- }
-
+ DCHECK(message_loop()->BelongsToCurrentThread());
view_->Paint();
}
void ChromotingClient::ProcessVideoPacket(const VideoPacket* packet,
Task* done) {
- if (!message_loop()->BelongsToCurrentThread()) {
- message_loop()->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &ChromotingClient::ProcessVideoPacket,
- packet, done));
- return;
- }
+ DCHECK(message_loop()->BelongsToCurrentThread());
// If the video packet is empty then drop it. Empty packets are used to
// maintain activity on the network.
@@ -162,47 +142,26 @@ void ChromotingClient::DispatchPacket() {
last_packet, decode_start));
}
-void ChromotingClient::OnConnectionOpened(protocol::ConnectionToHost* conn) {
- VLOG(1) << "ChromotingClient::OnConnectionOpened";
- Initialize();
- SetConnectionState(CONNECTED);
-}
-
-void ChromotingClient::OnConnectionClosed(protocol::ConnectionToHost* conn) {
- VLOG(1) << "ChromotingClient::OnConnectionClosed";
- SetConnectionState(DISCONNECTED);
-}
-
-void ChromotingClient::OnConnectionFailed(protocol::ConnectionToHost* conn) {
- VLOG(1) << "ChromotingClient::OnConnectionFailed";
- SetConnectionState(FAILED);
+void ChromotingClient::OnConnectionState(
+ protocol::ConnectionToHost::State state,
+ protocol::ConnectionToHost::Error error) {
+ DCHECK(message_loop()->BelongsToCurrentThread());
+ VLOG(1) << "ChromotingClient::OnConnectionState(" << state << ")";
+ if (state == protocol::ConnectionToHost::CONNECTED)
+ Initialize();
+ view_->SetConnectionState(state, error);
}
base::MessageLoopProxy* ChromotingClient::message_loop() {
return context_->network_message_loop();
}
-void ChromotingClient::SetConnectionState(ConnectionState s) {
- // TODO(ajwong): We actually may want state to be a shared variable. Think
- // through later.
- if (!message_loop()->BelongsToCurrentThread()) {
- message_loop()->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &ChromotingClient::SetConnectionState, s));
- return;
- }
-
- state_ = s;
- view_->SetConnectionState(s);
-}
-
void ChromotingClient::OnPacketDone(bool last_packet,
base::Time decode_start) {
if (!message_loop()->BelongsToCurrentThread()) {
- message_loop()->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &ChromotingClient::OnPacketDone,
- last_packet, decode_start));
+ thread_proxy_.PostTask(FROM_HERE, base::Bind(
+ &ChromotingClient::OnPacketDone, base::Unretained(this),
+ last_packet, decode_start));
return;
}
@@ -225,9 +184,8 @@ void ChromotingClient::OnPacketDone(bool last_packet,
void ChromotingClient::Initialize() {
if (!message_loop()->BelongsToCurrentThread()) {
- message_loop()->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &ChromotingClient::Initialize));
+ thread_proxy_.PostTask(FROM_HERE, base::Bind(
+ &ChromotingClient::Initialize, base::Unretained(this)));
return;
}
@@ -243,10 +201,9 @@ void ChromotingClient::Initialize() {
void ChromotingClient::BeginSessionResponse(
const protocol::LocalLoginStatus* msg, Task* done) {
if (!message_loop()->BelongsToCurrentThread()) {
- message_loop()->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &ChromotingClient::BeginSessionResponse,
- msg, done));
+ thread_proxy_.PostTask(FROM_HERE, base::Bind(
+ &ChromotingClient::BeginSessionResponse, base::Unretained(this),
+ msg, done));
return;
}
diff --git a/remoting/client/chromoting_client.h b/remoting/client/chromoting_client.h
index 0dfbb4c..5d18448 100644
--- a/remoting/client/chromoting_client.h
+++ b/remoting/client/chromoting_client.h
@@ -11,6 +11,7 @@
#include "base/task.h"
#include "base/time.h"
+#include "remoting/base/scoped_thread_proxy.h"
#include "remoting/client/client_config.h"
#include "remoting/client/chromoting_stats.h"
#include "remoting/client/chromoting_view.h"
@@ -59,9 +60,9 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
virtual void Repaint();
// ConnectionToHost::HostEventCallback implementation.
- virtual void OnConnectionOpened(protocol::ConnectionToHost* conn) OVERRIDE;
- virtual void OnConnectionClosed(protocol::ConnectionToHost* conn) OVERRIDE;
- virtual void OnConnectionFailed(protocol::ConnectionToHost* conn) OVERRIDE;
+ virtual void OnConnectionState(
+ protocol::ConnectionToHost::State state,
+ protocol::ConnectionToHost::Error error) OVERRIDE;
// ClientStub implementation.
virtual void BeginSessionResponse(const protocol::LocalLoginStatus* msg,
@@ -86,9 +87,6 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
// Initializes connection.
void Initialize();
- // Convenience method for modifying the state on this object's message loop.
- void SetConnectionState(ConnectionState s);
-
// If a packet is not being processed, dispatches a single message from the
// |received_packets_| queue.
void DispatchPacket();
@@ -111,8 +109,6 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
// If non-NULL, this is called when the client is done.
Task* client_done_;
- ConnectionState state_;
-
// Contains all video packets that have been received, but have not yet been
// processed.
//
@@ -129,6 +125,8 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
// Keep track of the last sequence number bounced back from the host.
int64 last_sequence_number_;
+ ScopedThreadProxy thread_proxy_;
+
DISALLOW_COPY_AND_ASSIGN(ChromotingClient);
};
diff --git a/remoting/client/chromoting_view.h b/remoting/client/chromoting_view.h
index 6911489..c546513 100644
--- a/remoting/client/chromoting_view.h
+++ b/remoting/client/chromoting_view.h
@@ -9,6 +9,7 @@
#include "base/memory/ref_counted.h"
#include "media/base/video_frame.h"
+#include "remoting/protocol/connection_to_host.h"
class MessageLoop;
@@ -22,14 +23,6 @@ static const uint32 kCreatedColor = 0xffccccff;
static const uint32 kDisconnectedColor = 0xff00ccff;
static const uint32 kFailedColor = 0xffcc00ff;
-// TODO(garykac): Move this into a proper class that keeps track of state.
-enum ConnectionState {
- CREATED,
- CONNECTED,
- DISCONNECTED,
- FAILED,
-};
-
// ChromotingView defines the behavior of an object that draws a view of the
// remote desktop. Its main function is to render the update stream onto the
// screen.
@@ -60,7 +53,8 @@ class ChromotingView {
virtual void UnsetSolidFill() = 0;
// Record the update the state of the connection, updating the UI as needed.
- virtual void SetConnectionState(ConnectionState s) = 0;
+ virtual void SetConnectionState(protocol::ConnectionToHost::State state,
+ protocol::ConnectionToHost::Error error) = 0;
// Update the status of the last login attempt. Updating the UI as needed.
// |success| is set to true if the last login successful otherwise false.
diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc
index 1fc4573..60bd867 100644
--- a/remoting/client/plugin/chromoting_instance.cc
+++ b/remoting/client/plugin/chromoting_instance.cc
@@ -184,8 +184,9 @@ void ChromotingInstance::Connect(const ClientConfig& config) {
client_->Start(xmpp_proxy);
VLOG(1) << "Connection status: Initializing";
- GetScriptableObject()->SetConnectionInfo(STATUS_INITIALIZING,
- QUALITY_UNKNOWN);
+ GetScriptableObject()->SetConnectionStatus(
+ ChromotingScriptableObject::STATUS_INITIALIZING,
+ ChromotingScriptableObject::ERROR_NONE);
}
void ChromotingInstance::Disconnect() {
@@ -204,7 +205,9 @@ void ChromotingInstance::Disconnect() {
input_handler_.reset();
host_connection_.reset();
- GetScriptableObject()->SetConnectionInfo(STATUS_CLOSED, QUALITY_UNKNOWN);
+ GetScriptableObject()->SetConnectionStatus(
+ ChromotingScriptableObject::STATUS_CLOSED,
+ ChromotingScriptableObject::ERROR_NONE);
}
void ChromotingInstance::DidChangeView(const pp::Rect& position,
@@ -302,8 +305,7 @@ ChromotingScriptableObject* ChromotingInstance::GetScriptableObject() {
void ChromotingInstance::SubmitLoginInfo(const std::string& username,
const std::string& password) {
- if (host_connection_->state() !=
- protocol::ConnectionToHost::STATE_CONNECTED) {
+ if (host_connection_->state() != protocol::ConnectionToHost::CONNECTED) {
LOG(INFO) << "Client not connected or already authenticated.";
return;
}
diff --git a/remoting/client/plugin/chromoting_scriptable_object.cc b/remoting/client/plugin/chromoting_scriptable_object.cc
index 28144c4..c19f8ff 100644
--- a/remoting/client/plugin/chromoting_scriptable_object.cc
+++ b/remoting/client/plugin/chromoting_scriptable_object.cc
@@ -30,8 +30,8 @@ const char kDesktopWidth[] = "desktopWidth";
const char kDesktopSizeUpdate[] = "desktopSizeUpdate";
const char kLoginChallenge[] = "loginChallenge";
const char kSendIq[] = "sendIq";
-const char kQualityAttribute[] = "quality";
const char kStatusAttribute[] = "status";
+const char kErrorAttribute[] = "error";
const char kVideoBandwidthAttribute[] = "videoBandwidth";
const char kVideoCaptureLatencyAttribute[] = "videoCaptureLatency";
const char kVideoEncodeLatencyAttribute[] = "videoEncodeLatency";
@@ -74,13 +74,15 @@ void ChromotingScriptableObject::Init() {
AddAttribute("STATUS_CLOSED", Var(STATUS_CLOSED));
AddAttribute("STATUS_FAILED", Var(STATUS_FAILED));
- // Connection quality.
- AddAttribute(kQualityAttribute, Var(QUALITY_UNKNOWN));
+ // Connection error.
+ AddAttribute(kErrorAttribute, Var(ERROR_NONE));
- // Connection quality values.
- AddAttribute("QUALITY_UNKNOWN", Var(QUALITY_UNKNOWN));
- AddAttribute("QUALITY_GOOD", Var(QUALITY_GOOD));
- AddAttribute("QUALITY_BAD", Var(QUALITY_BAD));
+ // Connection status values.
+ AddAttribute("ERROR_NONE", Var(ERROR_NONE));
+ AddAttribute("ERROR_HOST_IS_OFFLINE", Var(ERROR_HOST_IS_OFFLINE));
+ AddAttribute("ERROR_SESSION_REJECTED", Var(ERROR_SESSION_REJECTED));
+ AddAttribute("ERROR_INCOMPATIBLE_PROTOCOL", Var(ERROR_INCOMPATIBLE_PROTOCOL));
+ AddAttribute("ERROR_FAILURE_NONE", Var(ERROR_NETWORK_FAILURE));
// Debug info to display.
AddAttribute(kConnectionInfoUpdate, Var());
@@ -226,22 +228,26 @@ Var ChromotingScriptableObject::Call(const Var& method_name,
return (this->*(properties_[iter->second].method))(args, exception);
}
-void ChromotingScriptableObject::SetConnectionInfo(ConnectionStatus status,
- ConnectionQuality quality) {
- int status_index = property_names_[kStatusAttribute];
- int quality_index = property_names_[kQualityAttribute];
-
+void ChromotingScriptableObject::SetConnectionStatus(
+ ConnectionStatus status, ConnectionError error) {
VLOG(1) << "Connection status is updated: " << status;
- if (properties_[status_index].attribute.AsInt() != status ||
- properties_[quality_index].attribute.AsInt() != quality) {
- // Update the connection state properties..
+ bool signal = false;
+
+ int status_index = property_names_[kStatusAttribute];
+ if (properties_[status_index].attribute.AsInt() != status) {
properties_[status_index].attribute = Var(status);
- properties_[quality_index].attribute = Var(quality);
+ signal = true;
+ }
- // Signal the Chromoting Tab UI to get the update connection state values.
- SignalConnectionInfoChange();
+ int error_index = property_names_[kErrorAttribute];
+ if (properties_[error_index].attribute.AsInt() != error) {
+ properties_[error_index].attribute = Var(error);
+ signal = true;
}
+
+ if (signal)
+ SignalConnectionInfoChange();
}
void ChromotingScriptableObject::LogDebugInfo(const std::string& info) {
diff --git a/remoting/client/plugin/chromoting_scriptable_object.h b/remoting/client/plugin/chromoting_scriptable_object.h
index 04ef206..b138f9f 100644
--- a/remoting/client/plugin/chromoting_scriptable_object.h
+++ b/remoting/client/plugin/chromoting_scriptable_object.h
@@ -21,20 +21,19 @@
// readonly attribute unsigned short status;
//
// // Constants for connection status.
-// const unsigned short STATUS_UNKNOWN = 0;
-// const unsigned short STATUS_CONNECTING = 1;
-// const unsigned short STATUS_INITIALIZING = 2;
-// const unsigned short STATUS_CONNECTED = 3;
-// const unsigned short STATUS_CLOSED = 4;
-// const unsigned short STATUS_FAILED = 5;
+// const unsigned short STATUS_UNKNOWN;
+// const unsigned short STATUS_CONNECTING;
+// const unsigned short STATUS_INITIALIZING;
+// const unsigned short STATUS_CONNECTED;
+// const unsigned short STATUS_CLOSED;
+// const unsigned short STATUS_FAILED;
//
-// // Connection quality.
-// readonly attribute unsigned short quality;
-//
-// // Constants for connection quality
-// const unsigned short QUALITY_UNKNOWN = 0;
-// const unsigned short QUALITY_GOOD = 1;
-// const unsigned short QUALITY_BAD = 2;
+// // Constants for connection errors.
+// const unsigned short ERROR_NONE;
+// const unsigned short ERROR_HOST_IS_OFFLINE;
+// const unsigned short ERROR_SESSION_REJECTED;
+// const unsigned short ERROR_INCOMPATIBLE_PROTOCOL;
+// const unsigned short ERROR_NETWORK_FAILURE;
//
// // JS callback function so we can signal the JS UI when the connection
// // status has been updated.
@@ -129,25 +128,27 @@ namespace remoting {
class ChromotingInstance;
class PepperXmppProxy;
-enum ConnectionStatus {
- STATUS_UNKNOWN = 0,
- STATUS_CONNECTING,
- STATUS_INITIALIZING,
- STATUS_CONNECTED,
- STATUS_CLOSED,
- STATUS_FAILED,
-};
-
-enum ConnectionQuality {
- QUALITY_UNKNOWN = 0,
- QUALITY_GOOD,
- QUALITY_BAD,
-};
-
class ChromotingScriptableObject
: public pp::deprecated::ScriptableObject,
public base::SupportsWeakPtr<ChromotingScriptableObject> {
public:
+ enum ConnectionStatus {
+ STATUS_UNKNOWN = 0,
+ STATUS_CONNECTING,
+ STATUS_INITIALIZING,
+ STATUS_CONNECTED,
+ STATUS_CLOSED,
+ STATUS_FAILED,
+ };
+
+ enum ConnectionError {
+ ERROR_NONE = 0,
+ ERROR_HOST_IS_OFFLINE,
+ ERROR_SESSION_REJECTED,
+ ERROR_INCOMPATIBLE_PROTOCOL,
+ ERROR_NETWORK_FAILURE,
+ };
+
ChromotingScriptableObject(
ChromotingInstance* instance,
base::MessageLoopProxy* plugin_message_loop);
@@ -168,7 +169,7 @@ class ChromotingScriptableObject
const std::vector<pp::Var>& args,
pp::Var* exception);
- void SetConnectionInfo(ConnectionStatus status, ConnectionQuality quality);
+ void SetConnectionStatus(ConnectionStatus status, ConnectionError error);
void LogDebugInfo(const std::string& info);
void SetDesktopSize(int width, int height);
diff --git a/remoting/client/plugin/pepper_view.cc b/remoting/client/plugin/pepper_view.cc
index 6a58c78..c893d0b 100644
--- a/remoting/client/plugin/pepper_view.cc
+++ b/remoting/client/plugin/pepper_view.cc
@@ -19,6 +19,28 @@
namespace remoting {
+namespace {
+
+ChromotingScriptableObject::ConnectionError ConvertConnectionError(
+ protocol::ConnectionToHost::Error error) {
+ switch (error) {
+ case protocol::ConnectionToHost::OK:
+ return ChromotingScriptableObject::ERROR_NONE;
+ case protocol::ConnectionToHost::HOST_IS_OFFLINE:
+ return ChromotingScriptableObject::ERROR_HOST_IS_OFFLINE;
+ case protocol::ConnectionToHost::SESSION_REJECTED:
+ return ChromotingScriptableObject::ERROR_SESSION_REJECTED;
+ case protocol::ConnectionToHost::INCOMPATIBLE_PROTOCOL:
+ return ChromotingScriptableObject::ERROR_INCOMPATIBLE_PROTOCOL;
+ case protocol::ConnectionToHost::NETWORK_FAILURE:
+ return ChromotingScriptableObject::ERROR_NETWORK_FAILURE;
+ }
+ DLOG(FATAL) << "Unknown error code" << error;
+ return ChromotingScriptableObject::ERROR_NONE;
+}
+
+} // namespace
+
PepperView::PepperView(ChromotingInstance* instance, ClientContext* context)
: instance_(instance),
context_(context),
@@ -200,30 +222,40 @@ void PepperView::UnsetSolidFill() {
is_static_fill_ = false;
}
-void PepperView::SetConnectionState(ConnectionState state) {
+void PepperView::SetConnectionState(protocol::ConnectionToHost::State state,
+ protocol::ConnectionToHost::Error error) {
DCHECK(context_->main_message_loop()->BelongsToCurrentThread());
// TODO(hclam): Re-consider the way we communicate with Javascript.
ChromotingScriptableObject* scriptable_obj = instance_->GetScriptableObject();
switch (state) {
- case CREATED:
+ case protocol::ConnectionToHost::CONNECTING:
SetSolidFill(kCreatedColor);
- scriptable_obj->SetConnectionInfo(STATUS_CONNECTING, QUALITY_UNKNOWN);
+ scriptable_obj->SetConnectionStatus(
+ ChromotingScriptableObject::STATUS_CONNECTING,
+ ConvertConnectionError(error));
break;
- case CONNECTED:
- UnsetSolidFill();
+ case protocol::ConnectionToHost::CONNECTED:
scriptable_obj->SignalLoginChallenge();
break;
- case DISCONNECTED:
+ case protocol::ConnectionToHost::AUTHENTICATED:
+ UnsetSolidFill();
+ break;
+
+ case protocol::ConnectionToHost::CLOSED:
SetSolidFill(kDisconnectedColor);
- scriptable_obj->SetConnectionInfo(STATUS_CLOSED, QUALITY_UNKNOWN);
+ scriptable_obj->SetConnectionStatus(
+ ChromotingScriptableObject::STATUS_CLOSED,
+ ConvertConnectionError(error));
break;
- case FAILED:
+ case protocol::ConnectionToHost::FAILED:
SetSolidFill(kFailedColor);
- scriptable_obj->SetConnectionInfo(STATUS_FAILED, QUALITY_UNKNOWN);
+ scriptable_obj->SetConnectionStatus(
+ ChromotingScriptableObject::STATUS_FAILED,
+ ConvertConnectionError(error));
break;
}
}
@@ -233,10 +265,13 @@ void PepperView::UpdateLoginStatus(bool success, const std::string& info) {
// TODO(hclam): Re-consider the way we communicate with Javascript.
ChromotingScriptableObject* scriptable_obj = instance_->GetScriptableObject();
- if (success)
- scriptable_obj->SetConnectionInfo(STATUS_CONNECTED, QUALITY_UNKNOWN);
- else
+ if (success) {
+ scriptable_obj->SetConnectionStatus(
+ ChromotingScriptableObject::STATUS_CONNECTED,
+ ChromotingScriptableObject::ERROR_NONE);
+ } else {
scriptable_obj->SignalLoginChallenge();
+ }
}
bool PepperView::SetPluginSize(const SkISize& plugin_size) {
diff --git a/remoting/client/plugin/pepper_view.h b/remoting/client/plugin/pepper_view.h
index 1d52cff..0af344d 100644
--- a/remoting/client/plugin/pepper_view.h
+++ b/remoting/client/plugin/pepper_view.h
@@ -39,9 +39,11 @@ class PepperView : public ChromotingView,
virtual void Paint() OVERRIDE;
virtual void SetSolidFill(uint32 color) OVERRIDE;
virtual void UnsetSolidFill() OVERRIDE;
- virtual void SetConnectionState(ConnectionState state) OVERRIDE;
- virtual void UpdateLoginStatus(bool success, const std::string& info)
- OVERRIDE;
+ virtual void SetConnectionState(
+ protocol::ConnectionToHost::State state,
+ protocol::ConnectionToHost::Error error) OVERRIDE;
+ virtual void UpdateLoginStatus(bool success,
+ const std::string& info) OVERRIDE;
virtual double GetHorizontalScaleRatio() const OVERRIDE;
virtual double GetVerticalScaleRatio() const OVERRIDE;
diff --git a/remoting/client/plugin/pepper_view_proxy.cc b/remoting/client/plugin/pepper_view_proxy.cc
index be37706..119f154 100644
--- a/remoting/client/plugin/pepper_view_proxy.cc
+++ b/remoting/client/plugin/pepper_view_proxy.cc
@@ -71,15 +71,17 @@ void PepperViewProxy::UnsetSolidFill() {
view_->UnsetSolidFill();
}
-void PepperViewProxy::SetConnectionState(ConnectionState state) {
+void PepperViewProxy::SetConnectionState(
+ protocol::ConnectionToHost::State state,
+ protocol::ConnectionToHost::Error error) {
if (instance_ && !plugin_message_loop_->BelongsToCurrentThread()) {
plugin_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
- this, &PepperViewProxy::SetConnectionState, state));
+ this, &PepperViewProxy::SetConnectionState, state, error));
return;
}
if (view_)
- view_->SetConnectionState(state);
+ view_->SetConnectionState(state, error);
}
void PepperViewProxy::UpdateLoginStatus(bool success, const std::string& info) {
diff --git a/remoting/client/plugin/pepper_view_proxy.h b/remoting/client/plugin/pepper_view_proxy.h
index e6b7d0a..8a4914e 100644
--- a/remoting/client/plugin/pepper_view_proxy.h
+++ b/remoting/client/plugin/pepper_view_proxy.h
@@ -42,7 +42,9 @@ class PepperViewProxy : public base::RefCountedThreadSafe<PepperViewProxy>,
virtual void Paint() OVERRIDE;
virtual void SetSolidFill(uint32 color) OVERRIDE;
virtual void UnsetSolidFill() OVERRIDE;
- virtual void SetConnectionState(ConnectionState state) OVERRIDE;
+ virtual void SetConnectionState(
+ protocol::ConnectionToHost::State state,
+ protocol::ConnectionToHost::Error error) OVERRIDE;
virtual void UpdateLoginStatus(bool success, const std::string& info)
OVERRIDE;
diff --git a/remoting/protocol/connection_to_host.cc b/remoting/protocol/connection_to_host.cc
index 742f4f5..e2fe74a 100644
--- a/remoting/protocol/connection_to_host.cc
+++ b/remoting/protocol/connection_to_host.cc
@@ -35,7 +35,8 @@ ConnectionToHost::ConnectionToHost(
event_callback_(NULL),
client_stub_(NULL),
video_stub_(NULL),
- state_(STATE_EMPTY),
+ state_(CONNECTING),
+ error_(OK),
control_connected_(false),
input_connected_(false),
video_connected_(false) {
@@ -120,7 +121,7 @@ void ConnectionToHost::OnStateChange(
InitSession();
} else if (state == SignalStrategy::StatusObserver::CLOSED) {
VLOG(1) << "Connection closed.";
- event_callback_->OnConnectionClosed(this);
+ CloseOnError(NETWORK_FAILURE);
}
}
@@ -153,6 +154,20 @@ void ConnectionToHost::OnIncomingSession(
*response = SessionManager::DECLINE;
}
+void ConnectionToHost::OnClientAuthenticated() {
+ // TODO(hclam): Don't send anything except authentication request if it is
+ // not authenticated.
+ SetState(AUTHENTICATED, OK);
+
+ // Create and enable the input stub now that we're authenticated.
+ input_sender_.reset(
+ new InputSender(message_loop_, session_->event_channel()));
+}
+
+ConnectionToHost::State ConnectionToHost::state() const {
+ return state_;
+}
+
void ConnectionToHost::OnSessionStateChange(
Session::State state) {
DCHECK(message_loop_->BelongsToCurrentThread());
@@ -160,13 +175,28 @@ void ConnectionToHost::OnSessionStateChange(
switch (state) {
case Session::FAILED:
- CloseOnError();
+ switch (session_->error()) {
+ case Session::PEER_IS_OFFLINE:
+ CloseOnError(HOST_IS_OFFLINE);
+ break;
+ case Session::SESSION_REJECTED:
+ CloseOnError(SESSION_REJECTED);
+ break;
+ case Session::INCOMPATIBLE_PROTOCOL:
+ CloseOnError(INCOMPATIBLE_PROTOCOL);
+ break;
+ case Session::CHANNEL_CONNECTION_ERROR:
+ CloseOnError(NETWORK_FAILURE);
+ break;
+ case Session::OK:
+ DLOG(FATAL) << "Error code isn't set";
+ CloseOnError(NETWORK_FAILURE);
+ }
break;
case Session::CLOSED:
- state_ = STATE_CLOSED;
CloseChannels();
- event_callback_->OnConnectionClosed(this);
+ SetState(CLOSED, OK);
break;
case Session::CONNECTED:
@@ -179,7 +209,6 @@ void ConnectionToHost::OnSessionStateChange(
break;
case Session::CONNECTED_CHANNELS:
- state_ = STATE_CONNECTED;
host_control_sender_.reset(
new HostControlSender(message_loop_, session_->control_channel()));
dispatcher_.reset(new ClientMessageDispatcher());
@@ -199,7 +228,7 @@ void ConnectionToHost::OnSessionStateChange(
void ConnectionToHost::OnVideoChannelInitialized(bool successful) {
if (!successful) {
LOG(ERROR) << "Failed to connect video channel";
- CloseOnError();
+ CloseOnError(NETWORK_FAILURE);
return;
}
@@ -208,14 +237,15 @@ void ConnectionToHost::OnVideoChannelInitialized(bool successful) {
}
void ConnectionToHost::NotifyIfChannelsReady() {
- if (control_connected_ && input_connected_ && video_connected_)
- event_callback_->OnConnectionOpened(this);
+ if (control_connected_ && input_connected_ && video_connected_ &&
+ state_ == CONNECTING) {
+ SetState(CONNECTED, OK);
+ }
}
-void ConnectionToHost::CloseOnError() {
- state_ = STATE_FAILED;
+void ConnectionToHost::CloseOnError(Error error) {
CloseChannels();
- event_callback_->OnConnectionFailed(this);
+ SetState(FAILED, error);
}
void ConnectionToHost::CloseChannels() {
@@ -228,18 +258,16 @@ void ConnectionToHost::CloseChannels() {
video_reader_.reset();
}
-void ConnectionToHost::OnClientAuthenticated() {
- // TODO(hclam): Don't send anything except authentication request if it is
- // not authenticated.
- state_ = STATE_AUTHENTICATED;
-
- // Create and enable the input stub now that we're authenticated.
- input_sender_.reset(
- new InputSender(message_loop_, session_->event_channel()));
-}
+void ConnectionToHost::SetState(State state, Error error) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ // |error| should be specified only when |state| is set to FAILED.
+ DCHECK(state == FAILED || error == OK);
-ConnectionToHost::State ConnectionToHost::state() const {
- return state_;
+ if (state != state_) {
+ state_ = state;
+ error_ = error;
+ event_callback_->OnConnectionState(state_, error_);
+ }
}
} // namespace protocol
diff --git a/remoting/protocol/connection_to_host.h b/remoting/protocol/connection_to_host.h
index c8c1b44..fbf03e2 100644
--- a/remoting/protocol/connection_to_host.h
+++ b/remoting/protocol/connection_to_host.h
@@ -48,25 +48,27 @@ class ConnectionToHost : public SignalStrategy::StatusObserver,
public SessionManager::Listener {
public:
enum State {
- STATE_EMPTY,
- STATE_CONNECTED,
- STATE_AUTHENTICATED,
- STATE_FAILED,
- STATE_CLOSED,
+ CONNECTING,
+ CONNECTED,
+ AUTHENTICATED,
+ FAILED,
+ CLOSED,
+ };
+
+ enum Error {
+ OK,
+ HOST_IS_OFFLINE,
+ SESSION_REJECTED,
+ INCOMPATIBLE_PROTOCOL,
+ NETWORK_FAILURE,
};
class HostEventCallback {
public:
virtual ~HostEventCallback() {}
- // Called when the network connection is opened.
- virtual void OnConnectionOpened(ConnectionToHost* conn) = 0;
-
- // Called when the network connection is closed.
- virtual void OnConnectionClosed(ConnectionToHost* conn) = 0;
-
- // Called when the network connection has failed.
- virtual void OnConnectionFailed(ConnectionToHost* conn) = 0;
+ // Called when state of the connection changes.
+ virtual void OnConnectionState(State state, Error error) = 0;
};
ConnectionToHost(base::MessageLoopProxy* message_loop,
@@ -124,11 +126,13 @@ class ConnectionToHost : public SignalStrategy::StatusObserver,
// Callback for |video_reader_|.
void OnVideoPacket(VideoPacket* packet);
- void CloseOnError();
+ void CloseOnError(Error error);
// Stops writing in the channels.
void CloseChannels();
+ void SetState(State state, Error error);
+
scoped_refptr<base::MessageLoopProxy> message_loop_;
pp::Instance* pp_instance_;
bool allow_nat_traversal_;
@@ -158,6 +162,7 @@ class ConnectionToHost : public SignalStrategy::StatusObserver,
// Internal state of the connection.
State state_;
+ Error error_;
// State of the channels.
bool control_connected_;
diff --git a/remoting/protocol/session.h b/remoting/protocol/session.h
index 0697b16..aaecbf9 100644
--- a/remoting/protocol/session.h
+++ b/remoting/protocol/session.h
@@ -49,6 +49,7 @@ class Session : public base::NonThreadSafe {
FAILED,
};
+ // TODO(sergeyu): Move error codes to a separate file.
enum Error {
OK = 0,
PEER_IS_OFFLINE,
@@ -58,6 +59,9 @@ class Session : public base::NonThreadSafe {
};
typedef Callback1<State>::Type StateChangeCallback;
+
+ // TODO(sergeyu): Specify connection error code when channel
+ // connection fails.
typedef base::Callback<void(net::StreamSocket*)> StreamChannelCallback;
typedef base::Callback<void(net::Socket*)> DatagramChannelCallback;