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/rectangle_update_decoder.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 scoped_refptr
<FrameConsumerProxy
> frame_consumer
,
33 scoped_ptr
<AudioPlayer
> audio_player
)
35 task_runner_(client_context
->main_task_runner()),
36 connection_(connection
),
37 user_interface_(user_interface
),
38 host_capabilities_received_(false),
41 new RectangleUpdateDecoder(client_context
->main_task_runner(),
42 client_context
->decode_task_runner(),
45 audio_decode_scheduler_
.reset(new AudioDecodeScheduler(
46 client_context
->main_task_runner(),
47 client_context
->audio_decode_task_runner(),
48 audio_player
.Pass()));
52 ChromotingClient::~ChromotingClient() {
55 void ChromotingClient::Start(
56 SignalStrategy
* signal_strategy
,
57 scoped_ptr
<protocol::TransportFactory
> transport_factory
) {
58 DCHECK(task_runner_
->BelongsToCurrentThread());
60 scoped_ptr
<protocol::Authenticator
> authenticator(
61 new protocol::NegotiatingClientAuthenticator(
62 config_
.client_pairing_id
,
63 config_
.client_paired_secret
,
64 config_
.authentication_tag
,
65 config_
.fetch_secret_callback
,
66 user_interface_
->GetTokenFetcher(config_
.host_public_key
),
67 config_
.authentication_methods
));
69 // Create a WeakPtr to ourself for to use for all posted tasks.
70 weak_ptr_
= weak_factory_
.GetWeakPtr();
72 connection_
->Connect(signal_strategy
,
74 config_
.host_public_key
,
75 transport_factory
.Pass(),
80 rectangle_decoder_
.get(),
81 audio_decode_scheduler_
.get());
84 FrameProducer
* ChromotingClient::GetFrameProducer() {
85 return rectangle_decoder_
.get();
88 ChromotingStats
* ChromotingClient::GetStats() {
89 DCHECK(task_runner_
->BelongsToCurrentThread());
90 return rectangle_decoder_
->GetStats();
93 void ChromotingClient::SetCapabilities(
94 const protocol::Capabilities
& capabilities
) {
95 DCHECK(task_runner_
->BelongsToCurrentThread());
97 // Only accept the first |protocol::Capabilities| message.
98 if (host_capabilities_received_
) {
99 LOG(WARNING
) << "protocol::Capabilities has been received already.";
103 host_capabilities_received_
= true;
104 if (capabilities
.has_capabilities())
105 host_capabilities_
= capabilities
.capabilities();
107 VLOG(1) << "Host capabilities: " << host_capabilities_
;
109 // Calculate the set of capabilities enabled by both client and host and pass
111 user_interface_
->SetCapabilities(
112 IntersectCapabilities(config_
.capabilities
, host_capabilities_
));
115 void ChromotingClient::SetPairingResponse(
116 const protocol::PairingResponse
& pairing_response
) {
117 DCHECK(task_runner_
->BelongsToCurrentThread());
119 user_interface_
->SetPairingResponse(pairing_response
);
122 void ChromotingClient::DeliverHostMessage(
123 const protocol::ExtensionMessage
& message
) {
124 DCHECK(task_runner_
->BelongsToCurrentThread());
126 user_interface_
->DeliverHostMessage(message
);
129 void ChromotingClient::InjectClipboardEvent(
130 const protocol::ClipboardEvent
& event
) {
131 DCHECK(task_runner_
->BelongsToCurrentThread());
133 user_interface_
->GetClipboardStub()->InjectClipboardEvent(event
);
136 void ChromotingClient::SetCursorShape(
137 const protocol::CursorShapeInfo
& cursor_shape
) {
138 DCHECK(task_runner_
->BelongsToCurrentThread());
140 user_interface_
->GetCursorShapeStub()->SetCursorShape(cursor_shape
);
143 void ChromotingClient::OnConnectionState(
144 protocol::ConnectionToHost::State state
,
145 protocol::ErrorCode error
) {
146 DCHECK(task_runner_
->BelongsToCurrentThread());
147 VLOG(1) << "ChromotingClient::OnConnectionState(" << state
<< ")";
149 if (state
== protocol::ConnectionToHost::AUTHENTICATED
) {
151 } else if (state
== protocol::ConnectionToHost::CONNECTED
) {
152 OnChannelsConnected();
154 user_interface_
->OnConnectionState(state
, error
);
157 void ChromotingClient::OnConnectionReady(bool ready
) {
158 VLOG(1) << "ChromotingClient::OnConnectionReady(" << ready
<< ")";
159 user_interface_
->OnConnectionReady(ready
);
162 void ChromotingClient::OnAuthenticated() {
163 DCHECK(task_runner_
->BelongsToCurrentThread());
165 // Initialize the decoder.
166 rectangle_decoder_
->Initialize(connection_
->config());
167 if (connection_
->config().is_audio_enabled())
168 audio_decode_scheduler_
->Initialize(connection_
->config());
170 // Do not negotiate capabilities with the host if the host does not support
172 if (!connection_
->config().SupportsCapabilities()) {
173 VLOG(1) << "The host does not support any capabilities.";
175 host_capabilities_received_
= true;
176 user_interface_
->SetCapabilities(host_capabilities_
);
180 void ChromotingClient::OnChannelsConnected() {
181 DCHECK(task_runner_
->BelongsToCurrentThread());
183 // Negotiate capabilities with the host.
184 if (connection_
->config().SupportsCapabilities()) {
185 VLOG(1) << "Client capabilities: " << config_
.capabilities
;
187 protocol::Capabilities capabilities
;
188 capabilities
.set_capabilities(config_
.capabilities
);
189 connection_
->host_stub()->SetCapabilities(capabilities
);
193 } // namespace remoting