1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/client/chromoting_client.h"
8 #include "remoting/base/capabilities.h"
9 #include "remoting/client/audio_decode_scheduler.h"
10 #include "remoting/client/audio_player.h"
11 #include "remoting/client/client_context.h"
12 #include "remoting/client/client_user_interface.h"
13 #include "remoting/client/video_renderer.h"
14 #include "remoting/proto/audio.pb.h"
15 #include "remoting/proto/video.pb.h"
16 #include "remoting/protocol/authentication_method.h"
17 #include "remoting/protocol/connection_to_host.h"
18 #include "remoting/protocol/host_stub.h"
19 #include "remoting/protocol/negotiating_client_authenticator.h"
20 #include "remoting/protocol/session_config.h"
21 #include "remoting/protocol/transport.h"
25 using protocol::AuthenticationMethod
;
27 ChromotingClient::ChromotingClient(
28 const ClientConfig
& config
,
29 ClientContext
* client_context
,
30 protocol::ConnectionToHost
* connection
,
31 ClientUserInterface
* user_interface
,
32 VideoRenderer
* video_renderer
,
33 scoped_ptr
<AudioPlayer
> audio_player
)
35 task_runner_(client_context
->main_task_runner()),
36 connection_(connection
),
37 user_interface_(user_interface
),
38 video_renderer_(video_renderer
),
39 host_capabilities_received_(false),
42 audio_decode_scheduler_
.reset(new AudioDecodeScheduler(
43 client_context
->main_task_runner(),
44 client_context
->audio_decode_task_runner(),
45 audio_player
.Pass()));
49 ChromotingClient::~ChromotingClient() {
52 void ChromotingClient::Start(
53 SignalStrategy
* signal_strategy
,
54 scoped_ptr
<protocol::TransportFactory
> transport_factory
) {
55 DCHECK(task_runner_
->BelongsToCurrentThread());
57 scoped_ptr
<protocol::Authenticator
> authenticator(
58 new protocol::NegotiatingClientAuthenticator(
59 config_
.client_pairing_id
,
60 config_
.client_paired_secret
,
61 config_
.authentication_tag
,
62 config_
.fetch_secret_callback
,
63 user_interface_
->GetTokenFetcher(config_
.host_public_key
),
64 config_
.authentication_methods
));
66 // Create a WeakPtr to ourself for to use for all posted tasks.
67 weak_ptr_
= weak_factory_
.GetWeakPtr();
69 connection_
->Connect(signal_strategy
,
71 config_
.host_public_key
,
72 transport_factory
.Pass(),
78 audio_decode_scheduler_
.get());
81 void ChromotingClient::SetCapabilities(
82 const protocol::Capabilities
& capabilities
) {
83 DCHECK(task_runner_
->BelongsToCurrentThread());
85 // Only accept the first |protocol::Capabilities| message.
86 if (host_capabilities_received_
) {
87 LOG(WARNING
) << "protocol::Capabilities has been received already.";
91 host_capabilities_received_
= true;
92 if (capabilities
.has_capabilities())
93 host_capabilities_
= capabilities
.capabilities();
95 VLOG(1) << "Host capabilities: " << host_capabilities_
;
97 // Calculate the set of capabilities enabled by both client and host and pass
99 user_interface_
->SetCapabilities(
100 IntersectCapabilities(config_
.capabilities
, host_capabilities_
));
103 void ChromotingClient::SetPairingResponse(
104 const protocol::PairingResponse
& pairing_response
) {
105 DCHECK(task_runner_
->BelongsToCurrentThread());
107 user_interface_
->SetPairingResponse(pairing_response
);
110 void ChromotingClient::DeliverHostMessage(
111 const protocol::ExtensionMessage
& message
) {
112 DCHECK(task_runner_
->BelongsToCurrentThread());
114 user_interface_
->DeliverHostMessage(message
);
117 void ChromotingClient::InjectClipboardEvent(
118 const protocol::ClipboardEvent
& event
) {
119 DCHECK(task_runner_
->BelongsToCurrentThread());
121 user_interface_
->GetClipboardStub()->InjectClipboardEvent(event
);
124 void ChromotingClient::SetCursorShape(
125 const protocol::CursorShapeInfo
& cursor_shape
) {
126 DCHECK(task_runner_
->BelongsToCurrentThread());
128 user_interface_
->GetCursorShapeStub()->SetCursorShape(cursor_shape
);
131 void ChromotingClient::OnConnectionState(
132 protocol::ConnectionToHost::State state
,
133 protocol::ErrorCode error
) {
134 DCHECK(task_runner_
->BelongsToCurrentThread());
135 VLOG(1) << "ChromotingClient::OnConnectionState(" << state
<< ")";
137 if (state
== protocol::ConnectionToHost::AUTHENTICATED
) {
139 } else if (state
== protocol::ConnectionToHost::CONNECTED
) {
140 OnChannelsConnected();
142 user_interface_
->OnConnectionState(state
, error
);
145 void ChromotingClient::OnConnectionReady(bool ready
) {
146 VLOG(1) << "ChromotingClient::OnConnectionReady(" << ready
<< ")";
147 user_interface_
->OnConnectionReady(ready
);
150 void ChromotingClient::OnRouteChanged(const std::string
& channel_name
,
151 const protocol::TransportRoute
& route
) {
152 VLOG(0) << "Using " << protocol::TransportRoute::GetTypeString(route
.type
)
153 << " connection for " << channel_name
<< " channel";
154 user_interface_
->OnRouteChanged(channel_name
, route
);
157 void ChromotingClient::OnAuthenticated() {
158 DCHECK(task_runner_
->BelongsToCurrentThread());
160 // Initialize the decoder.
161 video_renderer_
->Initialize(connection_
->config());
162 if (connection_
->config().is_audio_enabled())
163 audio_decode_scheduler_
->Initialize(connection_
->config());
165 // Do not negotiate capabilities with the host if the host does not support
167 if (!connection_
->config().SupportsCapabilities()) {
168 VLOG(1) << "The host does not support any capabilities.";
170 host_capabilities_received_
= true;
171 user_interface_
->SetCapabilities(host_capabilities_
);
175 void ChromotingClient::OnChannelsConnected() {
176 DCHECK(task_runner_
->BelongsToCurrentThread());
178 // Negotiate capabilities with the host.
179 if (connection_
->config().SupportsCapabilities()) {
180 VLOG(1) << "Client capabilities: " << config_
.capabilities
;
182 protocol::Capabilities capabilities
;
183 capabilities
.set_capabilities(config_
.capabilities
);
184 connection_
->host_stub()->SetCapabilities(capabilities
);
188 } // namespace remoting