blob: f819a5feebdf12aff5eb2e4271e92ac348146577 [file] [log] [blame]
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001// Copyright 2013 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.
4
5#include "remoting/client/jni/chromoting_jni_instance.h"
6
7#include "base/bind.h"
8#include "base/logging.h"
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +01009#include "net/socket/client_socket_factory.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010010#include "remoting/client/audio_player.h"
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010011#include "remoting/client/jni/android_keymap.h"
Ben Murdochbbcdd452013-07-25 10:06:34 +010012#include "remoting/client/jni/chromoting_jni_runtime.h"
Ben Murdochbb1529c2013-08-08 10:24:53 +010013#include "remoting/protocol/host_stub.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010014#include "remoting/protocol/libjingle_transport_factory.h"
15
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010016// TODO(solb) Move into location shared with client plugin.
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010017const char* const kXmppServer = "talk.google.com";
18const int kXmppPort = 5222;
19const bool kXmppUseTls = true;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010020
21namespace remoting {
22
Ben Murdochbbcdd452013-07-25 10:06:34 +010023ChromotingJniInstance::ChromotingJniInstance(ChromotingJniRuntime* jni_runtime,
24 const char* username,
Ben Murdoch9ab55632013-07-18 11:57:30 +010025 const char* auth_token,
26 const char* host_jid,
27 const char* host_id,
Ben Murdochbb1529c2013-08-08 10:24:53 +010028 const char* host_pubkey,
29 const char* pairing_id,
30 const char* pairing_secret)
Ben Murdochbbcdd452013-07-25 10:06:34 +010031 : jni_runtime_(jni_runtime),
Ben Murdochbbcdd452013-07-25 10:06:34 +010032 host_id_(host_id),
Ben Murdochbb1529c2013-08-08 10:24:53 +010033 create_pairing_(false) {
Ben Murdochbbcdd452013-07-25 10:06:34 +010034 DCHECK(jni_runtime_->ui_task_runner()->BelongsToCurrentThread());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010035
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +010036 // Intialize XMPP config.
37 xmpp_config_.host = kXmppServer;
38 xmpp_config_.port = kXmppPort;
39 xmpp_config_.use_tls = kXmppUseTls;
40 xmpp_config_.username = username;
41 xmpp_config_.auth_token = auth_token;
42 xmpp_config_.auth_service = "oauth2";
43
44 // Initialize ClientConfig.
45 client_config_.host_jid = host_jid;
46 client_config_.host_public_key = host_pubkey;
47
48 client_config_.fetch_secret_callback =
49 base::Bind(&ChromotingJniInstance::FetchSecret, this);
50 client_config_.authentication_tag = host_id_;
51
52 client_config_.client_pairing_id = pairing_id;
53 client_config_.client_paired_secret = pairing_secret;
54
55 client_config_.authentication_methods.push_back(
56 protocol::AuthenticationMethod::FromString("spake2_pair"));
57 client_config_.authentication_methods.push_back(
58 protocol::AuthenticationMethod::FromString("spake2_hmac"));
59 client_config_.authentication_methods.push_back(
60 protocol::AuthenticationMethod::FromString("spake2_plain"));
61
62 // Post a task to start connection
Ben Murdochbbcdd452013-07-25 10:06:34 +010063 jni_runtime_->display_task_runner()->PostTask(
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010064 FROM_HERE,
65 base::Bind(&ChromotingJniInstance::ConnectToHostOnDisplayThread,
66 this));
67}
68
69ChromotingJniInstance::~ChromotingJniInstance() {}
70
71void ChromotingJniInstance::Cleanup() {
Ben Murdochbbcdd452013-07-25 10:06:34 +010072 if (!jni_runtime_->display_task_runner()->BelongsToCurrentThread()) {
73 jni_runtime_->display_task_runner()->PostTask(
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010074 FROM_HERE,
75 base::Bind(&ChromotingJniInstance::Cleanup, this));
76 return;
77 }
78
Ben Murdoch9ab55632013-07-18 11:57:30 +010079 // This must be destroyed on the display thread before the producer is gone.
80 view_.reset();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010081
Ben Murdoch9ab55632013-07-18 11:57:30 +010082 // The weak pointers must be invalidated on the same thread they were used.
83 view_weak_factory_->InvalidateWeakPtrs();
84
Ben Murdochbbcdd452013-07-25 10:06:34 +010085 jni_runtime_->network_task_runner()->PostTask(
86 FROM_HERE,
Ben Murdoch9ab55632013-07-18 11:57:30 +010087 base::Bind(&ChromotingJniInstance::DisconnectFromHostOnNetworkThread,
88 this));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010089}
90
Ben Murdochbb1529c2013-08-08 10:24:53 +010091void ChromotingJniInstance::ProvideSecret(const std::string& pin,
92 bool create_pairing) {
Ben Murdochbbcdd452013-07-25 10:06:34 +010093 DCHECK(jni_runtime_->ui_task_runner()->BelongsToCurrentThread());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010094 DCHECK(!pin_callback_.is_null());
95
Ben Murdochbb1529c2013-08-08 10:24:53 +010096 create_pairing_ = create_pairing;
97
Ben Murdochbbcdd452013-07-25 10:06:34 +010098 jni_runtime_->network_task_runner()->PostTask(FROM_HERE,
99 base::Bind(pin_callback_, pin));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100100}
101
Ben Murdoch9ab55632013-07-18 11:57:30 +0100102void ChromotingJniInstance::RedrawDesktop() {
Ben Murdochbbcdd452013-07-25 10:06:34 +0100103 if (!jni_runtime_->display_task_runner()->BelongsToCurrentThread()) {
104 jni_runtime_->display_task_runner()->PostTask(
Ben Murdoch9ab55632013-07-18 11:57:30 +0100105 FROM_HERE,
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100106 base::Bind(&ChromotingJniInstance::RedrawDesktop, this));
Ben Murdoch9ab55632013-07-18 11:57:30 +0100107 return;
108 }
109
Ben Murdochbbcdd452013-07-25 10:06:34 +0100110 jni_runtime_->RedrawCanvas();
Ben Murdoch9ab55632013-07-18 11:57:30 +0100111}
112
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100113void ChromotingJniInstance::PerformMouseAction(
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100114 int x, int y,
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100115 protocol::MouseEvent_MouseButton button,
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100116 bool button_down) {
Ben Murdochbbcdd452013-07-25 10:06:34 +0100117 if (!jni_runtime_->network_task_runner()->BelongsToCurrentThread()) {
118 jni_runtime_->network_task_runner()->PostTask(
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100119 FROM_HERE, base::Bind(&ChromotingJniInstance::PerformMouseAction,
120 this, x, y, button, button_down));
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100121 return;
122 }
123
124 protocol::MouseEvent action;
125 action.set_x(x);
126 action.set_y(y);
127 action.set_button(button);
128 if (button != protocol::MouseEvent::BUTTON_UNDEFINED)
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100129 action.set_button_down(button_down);
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100130
131 connection_->input_stub()->InjectMouseEvent(action);
132}
133
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100134void ChromotingJniInstance::PerformKeyboardAction(int key_code, bool key_down) {
135 if (!jni_runtime_->network_task_runner()->BelongsToCurrentThread()) {
136 jni_runtime_->network_task_runner()->PostTask(
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100137 FROM_HERE, base::Bind(&ChromotingJniInstance::PerformKeyboardAction,
138 this, key_code, key_down));
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100139 return;
140 }
141
142 uint32 usb_code = AndroidKeycodeToUsbKeycode(key_code);
143 if (usb_code) {
144 protocol::KeyEvent action;
145 action.set_usb_keycode(usb_code);
146 action.set_pressed(key_down);
147 connection_->input_stub()->InjectKeyEvent(action);
Ben Murdochba5b9a62013-08-12 14:20:17 +0100148 } else {
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100149 LOG(WARNING) << "Ignoring unknown keycode: " << key_code;
150 }
151}
152
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100153void ChromotingJniInstance::OnConnectionState(
154 protocol::ConnectionToHost::State state,
155 protocol::ErrorCode error) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100156 DCHECK(jni_runtime_->network_task_runner()->BelongsToCurrentThread());
157
158 if (create_pairing_ && state == protocol::ConnectionToHost::CONNECTED) {
159 LOG(INFO) << "Attempting to pair with host";
160 protocol::PairingRequest request;
161 request.set_client_name("Android");
162 connection_->host_stub()->RequestPairing(request);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100163 }
164
Ben Murdochbb1529c2013-08-08 10:24:53 +0100165 jni_runtime_->ui_task_runner()->PostTask(
166 FROM_HERE,
167 base::Bind(&ChromotingJniRuntime::ReportConnectionStatus,
168 base::Unretained(jni_runtime_),
169 state,
170 error));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100171}
172
173void ChromotingJniInstance::OnConnectionReady(bool ready) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100174 // We ignore this message, since OnConnectoinState tells us the same thing.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100175}
176
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100177void ChromotingJniInstance::SetCapabilities(const std::string& capabilities) {
178 NOTIMPLEMENTED();
179}
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100180
181void ChromotingJniInstance::SetPairingResponse(
182 const protocol::PairingResponse& response) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100183 LOG(INFO) << "Successfully established pairing with host";
184
185 jni_runtime_->ui_task_runner()->PostTask(
186 FROM_HERE,
187 base::Bind(&ChromotingJniRuntime::CommitPairingCredentials,
188 base::Unretained(jni_runtime_),
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100189 host_id_, response.client_id(), response.shared_secret()));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100190}
191
Ben Murdochc2db58b2013-08-14 11:51:42 +0100192void ChromotingJniInstance::DeliverHostMessage(
193 const protocol::ExtensionMessage& message) {
194 NOTIMPLEMENTED();
195}
196
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100197protocol::ClipboardStub* ChromotingJniInstance::GetClipboardStub() {
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100198 return this;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100199}
200
201protocol::CursorShapeStub* ChromotingJniInstance::GetCursorShapeStub() {
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100202 return this;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100203}
204
205scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>
206 ChromotingJniInstance::GetTokenFetcher(const std::string& host_public_key) {
207 // Return null to indicate that third-party authentication is unsupported.
208 return scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>();
209}
210
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100211void ChromotingJniInstance::InjectClipboardEvent(
212 const protocol::ClipboardEvent& event) {
213 NOTIMPLEMENTED();
214}
215
216void ChromotingJniInstance::SetCursorShape(
217 const protocol::CursorShapeInfo& shape) {
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100218 if (!jni_runtime_->display_task_runner()->BelongsToCurrentThread()) {
219 jni_runtime_->display_task_runner()->PostTask(
220 FROM_HERE,
221 base::Bind(&ChromotingJniInstance::SetCursorShape, this, shape));
222 return;
223 }
224
225 jni_runtime_->UpdateCursorShape(shape);
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100226}
227
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100228void ChromotingJniInstance::ConnectToHostOnDisplayThread() {
Ben Murdochbbcdd452013-07-25 10:06:34 +0100229 DCHECK(jni_runtime_->display_task_runner()->BelongsToCurrentThread());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100230
Ben Murdochbbcdd452013-07-25 10:06:34 +0100231 view_.reset(new JniFrameConsumer(jni_runtime_));
Ben Murdoch9ab55632013-07-18 11:57:30 +0100232 view_weak_factory_.reset(new base::WeakPtrFactory<JniFrameConsumer>(
233 view_.get()));
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100234 frame_consumer_ = new FrameConsumerProxy(jni_runtime_->display_task_runner(),
235 view_weak_factory_->GetWeakPtr());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100236
Ben Murdochbbcdd452013-07-25 10:06:34 +0100237 jni_runtime_->network_task_runner()->PostTask(
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100238 FROM_HERE,
239 base::Bind(&ChromotingJniInstance::ConnectToHostOnNetworkThread,
240 this));
241}
242
243void ChromotingJniInstance::ConnectToHostOnNetworkThread() {
Ben Murdochbbcdd452013-07-25 10:06:34 +0100244 DCHECK(jni_runtime_->network_task_runner()->BelongsToCurrentThread());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100245
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100246 client_context_.reset(new ClientContext(
Ben Murdochbbcdd452013-07-25 10:06:34 +0100247 jni_runtime_->network_task_runner().get()));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100248 client_context_->Start();
249
250 connection_.reset(new protocol::ConnectionToHost(true));
251
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100252 client_.reset(new ChromotingClient(
253 client_config_, client_context_.get(), connection_.get(),
254 this, frame_consumer_, scoped_ptr<AudioPlayer>()));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100255
Ben Murdoch9ab55632013-07-18 11:57:30 +0100256 view_->set_frame_producer(client_->GetFrameProducer());
257
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100258 signaling_.reset(new XmppSignalStrategy(
259 net::ClientSocketFactory::GetDefaultFactory(),
260 jni_runtime_->url_requester(), xmpp_config_));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100261
262 network_settings_.reset(new NetworkSettings(
Ben Murdoch558790d2013-07-30 15:19:42 +0100263 NetworkSettings::NAT_TRAVERSAL_ENABLED));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100264 scoped_ptr<protocol::TransportFactory> fact(
265 protocol::LibjingleTransportFactory::Create(
266 *network_settings_,
Ben Murdochbbcdd452013-07-25 10:06:34 +0100267 jni_runtime_->url_requester()));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100268
269 client_->Start(signaling_.get(), fact.Pass());
270}
271
Ben Murdoch9ab55632013-07-18 11:57:30 +0100272void ChromotingJniInstance::DisconnectFromHostOnNetworkThread() {
Ben Murdochbbcdd452013-07-25 10:06:34 +0100273 DCHECK(jni_runtime_->network_task_runner()->BelongsToCurrentThread());
Ben Murdoch9ab55632013-07-18 11:57:30 +0100274
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100275 host_id_.clear();
Ben Murdoch9ab55632013-07-18 11:57:30 +0100276
277 // |client_| must be torn down before |signaling_|.
278 connection_.reset();
279 client_.reset();
280}
281
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100282void ChromotingJniInstance::FetchSecret(
283 bool pairable,
284 const protocol::SecretFetchedCallback& callback) {
Ben Murdochbbcdd452013-07-25 10:06:34 +0100285 if (!jni_runtime_->ui_task_runner()->BelongsToCurrentThread()) {
286 jni_runtime_->ui_task_runner()->PostTask(
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100287 FROM_HERE, base::Bind(&ChromotingJniInstance::FetchSecret,
288 this, pairable, callback));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100289 return;
290 }
291
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100292 if (!client_config_.client_pairing_id.empty()) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100293 // We attempted to connect using an existing pairing that was rejected.
294 // Unless we forget about the stale credentials, we'll continue trying them.
295 LOG(INFO) << "Deleting rejected pairing credentials";
296 jni_runtime_->CommitPairingCredentials(host_id_, "", "");
297 }
298
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100299 pin_callback_ = callback;
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100300 jni_runtime_->DisplayAuthenticationPrompt(pairable);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100301}
302
303} // namespace remoting