Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(581)

Side by Side Diff: remoting/ios/bridge/client_instance.cc

Issue 186733007: iOS Chromoting Client (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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/ios/bridge/client_instance.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "net/socket/client_socket_factory.h"
10 #include "remoting/client/audio_player.h"
11 #include "remoting/client/software_video_renderer.h"
12 #include "remoting/client/plugin/delegating_signal_strategy.h"
13 #include "remoting/jingle_glue/chromium_port_allocator.h"
14 #include "remoting/protocol/host_stub.h"
15 #include "remoting/protocol/libjingle_transport_factory.h"
16
17 #include "remoting/ios/bridge/client_bridge.h"
18
19 namespace {
20 const char* const kXmppServer = "talk.google.com";
21 const int kXmppPort = 5222;
22 const bool kXmppUseTls = true;
23 } // namespace
24
25 namespace remoting {
26
27 ClientInstance::ClientInstance(ClientBridge* bridge,
28 const char* username,
29 const char* auth_token,
30 const char* host_jid,
31 const char* host_id,
32 const char* host_pubkey,
33 const char* pairing_id,
34 const char* pairing_secret)
35 : bridge_(bridge),
36 host_id_(host_id),
37 client_context_(bridge_->network_task_runner().get()),
38 create_pairing_(false) {
39 DCHECK(bridge_->ui_task_runner()->BelongsToCurrentThread());
40
41 // Intialize XMPP config.
42 xmpp_config_.host = kXmppServer;
43 xmpp_config_.port = kXmppPort;
44 xmpp_config_.use_tls = kXmppUseTls;
45 xmpp_config_.username = username;
46 xmpp_config_.auth_token = auth_token;
47 xmpp_config_.auth_service = "oauth2";
48
49 // Initialize ClientConfig.
50 client_config_.host_jid = host_jid;
51 client_config_.host_public_key = host_pubkey;
52
53 client_config_.fetch_secret_callback =
54 base::Bind(&ClientInstance::FetchSecret, this);
55 client_config_.authentication_tag = host_id_;
56
57 client_config_.client_pairing_id = pairing_id;
58 client_config_.client_paired_secret = pairing_secret;
59
60 client_config_.authentication_methods.push_back(
61 protocol::AuthenticationMethod::FromString("spake2_pair"));
62 client_config_.authentication_methods.push_back(
63 protocol::AuthenticationMethod::FromString("spake2_hmac"));
64 client_config_.authentication_methods.push_back(
65 protocol::AuthenticationMethod::FromString("spake2_plain"));
66
67 // Post a task to start connection
68 bridge_->network_task_runner()->PostTask(
69 FROM_HERE,
70 base::Bind(&ClientInstance::ConnectToHostOnNetworkThread, this));
71 }
72
73 ClientInstance::~ClientInstance() {}
74
75 void ClientInstance::Cleanup() {
76 DCHECK(bridge_->ui_task_runner()->BelongsToCurrentThread());
77
78 bridge_->network_task_runner()->PostTask(
79 FROM_HERE,
80 base::Bind(&ClientInstance::DisconnectFromHostOnNetworkThread, this));
81 }
82
83 // CLIENT reporting user provided PIN
84 void ClientInstance::ProvideSecret(const std::string& pin,
85 bool create_pairing) {
86 DCHECK(bridge_->ui_task_runner()->BelongsToCurrentThread());
87 DCHECK(!pin_callback_.is_null());
88
89 create_pairing_ = create_pairing;
90
91 bridge_->network_task_runner()->PostTask(FROM_HERE,
92 base::Bind(pin_callback_, pin));
93 }
94
95 // CLIENT invoked mouse input
96 void ClientInstance::PerformMouseAction(
97 const webrtc::DesktopVector& position,
98 const webrtc::DesktopVector& wheel_delta,
99 int /* protocol::MouseEvent_MouseButton */ whichButton,
100 bool button_down) {
101 // Button must be within the bounds of the MouseEvent_MouseButton enum.
102 DCHECK(whichButton >= 0 && whichButton < 5);
103
104 protocol::MouseEvent_MouseButton mButton =
105 static_cast<remoting::protocol::MouseEvent_MouseButton>(whichButton);
106
107 if (!bridge_->network_task_runner()->BelongsToCurrentThread()) {
dcaiafa 2014/03/19 01:14:15 Move this to the top of the function.
aboone 2014/03/21 16:42:07 Done.
108 bridge_->network_task_runner()->PostTask(
109 FROM_HERE,
110 base::Bind(&ClientInstance::PerformMouseAction,
111 this,
112 position,
113 wheel_delta,
114 mButton,
115 button_down));
116 return;
117 }
118
119 protocol::MouseEvent action;
120 action.set_x(position.x());
121 action.set_y(position.y());
122 action.set_wheel_delta_x(wheel_delta.x());
123 action.set_wheel_delta_y(wheel_delta.y());
124 action.set_button(mButton);
125 if (mButton != protocol::MouseEvent::BUTTON_UNDEFINED)
126 action.set_button_down(button_down);
127
128 connection_->input_stub()->InjectMouseEvent(action);
129 }
130
131 // CLIENT invoked keyboard input
132 void ClientInstance::PerformKeyboardAction(int key_code, bool key_down) {
133 if (!bridge_->network_task_runner()->BelongsToCurrentThread()) {
134 bridge_->network_task_runner()->PostTask(
135 FROM_HERE,
136 base::Bind(
137 &ClientInstance::PerformKeyboardAction, this, key_code, key_down));
138 return;
139 }
140
141 protocol::KeyEvent action;
142 action.set_usb_keycode(key_code);
143 action.set_pressed(key_down);
144 connection_->input_stub()->InjectKeyEvent(action);
145 }
146
147 // HOST reporting Connections State and/or Error
148 void ClientInstance::OnConnectionState(protocol::ConnectionToHost::State state,
149 protocol::ErrorCode error) {
150 if (!bridge_->ui_task_runner()->BelongsToCurrentThread()) {
151 bridge_->ui_task_runner()->PostTask(
152 FROM_HERE,
153 base::Bind(&ClientInstance::OnConnectionState, this, state, error));
154 return;
155 }
156
157 if (create_pairing_ && state == protocol::ConnectionToHost::CONNECTED) {
158 VLOG(1) << "Attempting to pair with host";
159 protocol::PairingRequest request;
160 request.set_client_name("iPad");
161 connection_->host_stub()->RequestPairing(request);
162 }
163
164 bridge_->ui_task_runner()->PostTask(
165 FROM_HERE,
166 base::Bind(&ClientBridge::ReportConnectionStatus,
167 base::Unretained(bridge_.get()),
dcaiafa 2014/03/19 01:14:15 ClientBridge is currently RefCounted, so there sho
aboone 2014/03/21 16:42:07 Done.
168 state,
169 error));
170 }
171
172 void ClientInstance::OnConnectionReady(bool ready) {
173 // We ignore this message, since OnConnectoinState tells us the same thing.
174 }
175
176 void ClientInstance::OnRouteChanged(const std::string& channel_name,
177 const protocol::TransportRoute& route) {
178 VLOG(1) << "Using " << protocol::TransportRoute::GetTypeString(route.type)
179 << " connection for " << channel_name << " channel";
180 }
181
182 void ClientInstance::SetCapabilities(const std::string& capabilities) {
183 video_renderer_->Initialize(connection_->config());
184 }
185
186 // HOST accepted client creditials, and response
187 void ClientInstance::SetPairingResponse(
188 const protocol::PairingResponse& response) {
189 VLOG(1) << "Successfully established pairing with host";
190
191 bridge_->ui_task_runner()->PostTask(
192 FROM_HERE,
193 base::Bind(&ClientBridge::CommitPairingCredentials,
194 base::Unretained(bridge_.get()),
dcaiafa 2014/03/19 01:14:15 Same as OnConnectionState().
aboone 2014/03/21 16:42:07 Done.
195 host_id_,
196 response.client_id(),
197 response.shared_secret()));
198 }
199
200 void ClientInstance::DeliverHostMessage(
201 const protocol::ExtensionMessage& message) {
202 NOTIMPLEMENTED();
203 }
204
205 // THIS inhereits protocol::ClipboardStub, returning a view of THIS as a
206 // protocol::ClipboardStub
207 protocol::ClipboardStub* ClientInstance::GetClipboardStub() { return this; }
208
209 // THIS inhereits protocol::CursorShapeStub, returning a view of THIS as a
210 // protocol::CursorShapeStub
211 protocol::CursorShapeStub* ClientInstance::GetCursorShapeStub() { return this; }
212
213 scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>
214 ClientInstance::GetTokenFetcher(const std::string& host_public_key) {
215 // Return null to indicate that third-party authentication is unsupported.
216 return scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>();
217 }
218
219 void ClientInstance::InjectClipboardEvent(
220 const protocol::ClipboardEvent& event) {
221 NOTIMPLEMENTED();
222 }
223
224 // HOST delivering a Cursor (mouse) update
225 void ClientInstance::SetCursorShape(const protocol::CursorShapeInfo& shape) {
226 if (!bridge_->ui_task_runner()->BelongsToCurrentThread()) {
227 bridge_->ui_task_runner()->PostTask(
228 FROM_HERE, base::Bind(&ClientInstance::SetCursorShape, this, shape));
229 return;
230 }
231
232 bridge_->UpdateCursorShape(shape);
233 }
234
235 // Create a thread to receive and package Canvas (desktop) updates
236 void ClientInstance::ConnectToHostOnNetworkThread() {
237 DCHECK(bridge_->network_task_runner()->BelongsToCurrentThread());
238
239 view_.reset(
240 new FrameConsumerBridge(bridge_->BindToFrameConsumerBridgeCallback()));
dcaiafa 2014/03/19 01:14:15 Create the binding on site instead of using a help
aboone 2014/03/21 16:42:07 Done.
241 view_weak_factory_.reset(
dcaiafa 2014/03/19 01:14:15 Move the WeakPtrFactory into FrameConsumerBridge,
aboone 2014/03/21 16:42:07 Done.
242 new base::WeakPtrFactory<FrameConsumer>(view_.get()));
243
244 client_context_.Start();
245
246 scoped_refptr<FrameConsumerProxy> consumer_proxy = new FrameConsumerProxy(
247 bridge_->network_task_runner(), view_weak_factory_->GetWeakPtr());
248
249 SoftwareVideoRenderer* renderer =
250 new SoftwareVideoRenderer(client_context_.main_task_runner(),
251 client_context_.decode_task_runner(),
252 consumer_proxy);
253
254 view_->Initialize(renderer);
255 video_renderer_.reset(renderer);
256
257 connection_.reset(new protocol::ConnectionToHost(true));
258
259 client_.reset(new ChromotingClient(client_config_,
260 &client_context_,
261 connection_.get(),
262 this,
263 video_renderer_.get(),
264 scoped_ptr<AudioPlayer>()));
265
266 signaling_.reset(
267 new XmppSignalStrategy(net::ClientSocketFactory::GetDefaultFactory(),
268 bridge_->url_requester(),
269 xmpp_config_));
270
271 NetworkSettings network_settings(NetworkSettings::NAT_TRAVERSAL_ENABLED);
272
273 scoped_ptr<ChromiumPortAllocator> port_allocator(
274 ChromiumPortAllocator::Create(bridge_->url_requester(),
275 network_settings));
276
277 scoped_ptr<protocol::TransportFactory> transport_factory(
278 new protocol::LibjingleTransportFactory(
279 signaling_.get(),
280 port_allocator.PassAs<cricket::HttpPortAllocatorBase>(),
281 network_settings));
282
283 client_->Start(signaling_.get(), transport_factory.Pass());
284 }
285
286 void ClientInstance::DisconnectFromHostOnNetworkThread() {
287 DCHECK(bridge_->network_task_runner()->BelongsToCurrentThread());
288
289 // This must be destroyed on the network thread before the producer is gone.
290 view_.reset();
291
292 // The weak pointers must be invalidated on the same thread they were used.
293 view_weak_factory_->InvalidateWeakPtrs();
294
295 host_id_.clear();
296
297 // |client_| must be torn down before |signaling_|.
298 connection_.reset();
299 client_.reset();
300 client_context_.Stop();
301 }
302
303 // HOST attempts to continue automatically with previously supplied credentials,
304 // if it can't it requests the user's PIN.
305 void ClientInstance::FetchSecret(
306 bool pairable,
307 const protocol::SecretFetchedCallback& callback) {
308 if (!bridge_->ui_task_runner()->BelongsToCurrentThread()) {
309 bridge_->ui_task_runner()->PostTask(
310 FROM_HERE,
311 base::Bind(&ClientInstance::FetchSecret, this, pairable, callback));
312 return;
313 }
314
315 if (!client_config_.client_pairing_id.empty()) {
316 // We attempted to connect using an existing pairing that was rejected.
317 // Unless we forget about the stale credentials, we'll continue trying them.
318 VLOG(1) << "Deleting rejected pairing credentials";
319 bridge_->CommitPairingCredentials(host_id_, "", "");
320 }
321
322 pin_callback_ = callback;
323 bridge_->DisplayAuthenticationPrompt(pairable);
324 }
325
326 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698