OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/host/it2me/it2me_host.h" | 5 #include "remoting/host/it2me/it2me_host.h" |
6 | 6 |
7 #include <cstdint> | 7 #include <cstdint> |
8 #include <memory> | 8 #include <memory> |
9 #include <string> | 9 #include <string> |
10 #include <utility> | 10 #include <utility> |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 host_context_->video_capture_task_runner(), | 92 host_context_->video_capture_task_runner(), |
93 host_context_->input_task_runner(), host_context_->ui_task_runner())); | 93 host_context_->input_task_runner(), host_context_->ui_task_runner())); |
94 | 94 |
95 // Start monitoring configured policies. | 95 // Start monitoring configured policies. |
96 policy_watcher_->StartWatching( | 96 policy_watcher_->StartWatching( |
97 base::Bind(&It2MeHost::OnPolicyUpdate, this), | 97 base::Bind(&It2MeHost::OnPolicyUpdate, this), |
98 base::Bind(&It2MeHost::OnPolicyError, this)); | 98 base::Bind(&It2MeHost::OnPolicyError, this)); |
99 | 99 |
100 // Switch to the network thread to start the actual connection. | 100 // Switch to the network thread to start the actual connection. |
101 host_context_->network_task_runner()->PostTask( | 101 host_context_->network_task_runner()->PostTask( |
102 FROM_HERE, base::Bind(&It2MeHost::ShowConfirmationPrompt, this)); | 102 FROM_HERE, base::Bind(&It2MeHost::ReadPolicyAndConnect, this)); |
103 } | 103 } |
104 | 104 |
105 void It2MeHost::Disconnect() { | 105 void It2MeHost::Disconnect() { |
106 DCHECK(task_runner_->BelongsToCurrentThread()); | 106 DCHECK(task_runner_->BelongsToCurrentThread()); |
107 host_context_->network_task_runner()->PostTask( | 107 host_context_->network_task_runner()->PostTask( |
108 FROM_HERE, base::Bind(&It2MeHost::DisconnectOnNetworkThread, this)); | 108 FROM_HERE, base::Bind(&It2MeHost::DisconnectOnNetworkThread, this)); |
109 } | 109 } |
110 | 110 |
111 void It2MeHost::DisconnectOnNetworkThread() { | 111 void It2MeHost::DisconnectOnNetworkThread() { |
112 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); | 112 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
(...skipping 30 matching lines...) Expand all Loading... |
143 DCHECK(task_runner_->BelongsToCurrentThread()); | 143 DCHECK(task_runner_->BelongsToCurrentThread()); |
144 host_context_->network_task_runner()->PostTask( | 144 host_context_->network_task_runner()->PostTask( |
145 FROM_HERE, base::Bind(&It2MeHost::RequestNatPolicy, this)); | 145 FROM_HERE, base::Bind(&It2MeHost::RequestNatPolicy, this)); |
146 return; | 146 return; |
147 } | 147 } |
148 | 148 |
149 if (policy_received_) | 149 if (policy_received_) |
150 UpdateNatPolicy(nat_traversal_enabled_); | 150 UpdateNatPolicy(nat_traversal_enabled_); |
151 } | 151 } |
152 | 152 |
153 void It2MeHost::ShowConfirmationPrompt() { | |
154 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); | |
155 | |
156 SetState(kStarting, ""); | |
157 | |
158 std::unique_ptr<It2MeConfirmationDialog> confirmation_dialog = | |
159 confirmation_dialog_factory_->Create(); | |
160 | |
161 // TODO(dcaiafa): Remove after dialog implementations for all platforms exist. | |
162 if (!confirmation_dialog) { | |
163 ReadPolicyAndConnect(); | |
164 return; | |
165 } | |
166 | |
167 confirmation_dialog_proxy_.reset( | |
168 new It2MeConfirmationDialogProxy(host_context_->ui_task_runner(), | |
169 std::move(confirmation_dialog))); | |
170 | |
171 confirmation_dialog_proxy_->Show( | |
172 base::Bind(&It2MeHost::OnConfirmationResult, base::Unretained(this))); | |
173 } | |
174 | |
175 void It2MeHost::OnConfirmationResult(It2MeConfirmationDialog::Result result) { | |
176 switch (result) { | |
177 case It2MeConfirmationDialog::Result::OK: | |
178 ReadPolicyAndConnect(); | |
179 break; | |
180 | |
181 case It2MeConfirmationDialog::Result::CANCEL: | |
182 DisconnectOnNetworkThread(); | |
183 break; | |
184 | |
185 default: | |
186 NOTREACHED(); | |
187 return; | |
188 } | |
189 } | |
190 | |
191 void It2MeHost::ReadPolicyAndConnect() { | 153 void It2MeHost::ReadPolicyAndConnect() { |
192 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); | 154 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
193 DCHECK_EQ(kStarting, state_); | 155 DCHECK_EQ(kDisconnected, state_); |
| 156 |
| 157 SetState(kStarting, ""); |
194 | 158 |
195 // Only proceed to FinishConnect() if at least one policy update has been | 159 // Only proceed to FinishConnect() if at least one policy update has been |
196 // received. | 160 // received. Otherwise, create the policy watcher and thunk the connect. |
197 if (policy_received_) { | 161 if (policy_received_) { |
198 FinishConnect(); | 162 FinishConnect(); |
199 } else { | 163 } else { |
200 // Otherwise, create the policy watcher, and thunk the connect. | 164 pending_connect_ = base::Bind(&It2MeHost::FinishConnect, this); |
201 pending_connect_ = | |
202 base::Bind(&It2MeHost::FinishConnect, this); | |
203 } | 165 } |
204 } | 166 } |
205 | 167 |
206 void It2MeHost::FinishConnect() { | 168 void It2MeHost::FinishConnect() { |
207 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); | 169 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
208 | 170 |
209 if (state_ != kStarting) { | 171 if (state_ != kStarting) { |
210 // Host has been stopped while we were fetching policy. | 172 // Host has been stopped while we were fetching policy. |
211 return; | 173 return; |
212 } | 174 } |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 } | 266 } |
305 } | 267 } |
306 | 268 |
307 void It2MeHost::OnClientConnected(const std::string& jid) { | 269 void It2MeHost::OnClientConnected(const std::string& jid) { |
308 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); | 270 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
309 | 271 |
310 // ChromotingHost doesn't allow multiple concurrent connection and the | 272 // ChromotingHost doesn't allow multiple concurrent connection and the |
311 // host is destroyed in OnClientDisconnected() after the first connection. | 273 // host is destroyed in OnClientDisconnected() after the first connection. |
312 CHECK_NE(state_, kConnected); | 274 CHECK_NE(state_, kConnected); |
313 | 275 |
314 std::string client_username = jid; | 276 std::string client_username; |
315 size_t pos = client_username.find('/'); | 277 if (!SplitJidResource(jid, &client_username, /*resource=*/nullptr)) { |
316 if (pos != std::string::npos) | 278 LOG(WARNING) << "Incorrectly formatted JID received: " << jid; |
317 client_username.replace(pos, std::string::npos, ""); | 279 client_username = jid; |
| 280 } |
318 | 281 |
319 HOST_LOG << "Client " << client_username << " connected."; | 282 HOST_LOG << "Client " << client_username << " connected."; |
320 | 283 |
321 // Pass the client user name to the script object before changing state. | 284 // Pass the client user name to the script object before changing state. |
322 task_runner_->PostTask( | 285 task_runner_->PostTask( |
323 FROM_HERE, base::Bind(&It2MeHost::Observer::OnClientAuthenticated, | 286 FROM_HERE, base::Bind(&It2MeHost::Observer::OnClientAuthenticated, |
324 observer_, client_username)); | 287 observer_, client_username)); |
325 | 288 |
326 SetState(kConnected, ""); | 289 SetState(kConnected, ""); |
327 } | 290 } |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 task_runner_->PostTask( | 478 task_runner_->PostTask( |
516 FROM_HERE, base::Bind(&It2MeHost::Observer::OnStoreAccessCode, | 479 FROM_HERE, base::Bind(&It2MeHost::Observer::OnStoreAccessCode, |
517 observer_, access_code, lifetime)); | 480 observer_, access_code, lifetime)); |
518 | 481 |
519 SetState(kReceivedAccessCode, ""); | 482 SetState(kReceivedAccessCode, ""); |
520 } | 483 } |
521 | 484 |
522 void It2MeHost::ValidateConnectionDetails( | 485 void It2MeHost::ValidateConnectionDetails( |
523 const std::string& remote_jid, | 486 const std::string& remote_jid, |
524 const protocol::ValidatingAuthenticator::ResultCallback& result_callback) { | 487 const protocol::ValidatingAuthenticator::ResultCallback& result_callback) { |
| 488 // First ensure the JID we received is valid. |
| 489 std::string client_username; |
| 490 if (!SplitJidResource(remote_jid, &client_username, /*resource=*/nullptr)) { |
| 491 LOG(ERROR) << "Rejecting incoming connection from " << remote_jid |
| 492 << ": Invalid JID."; |
| 493 result_callback.Run( |
| 494 protocol::ValidatingAuthenticator::Result::ERROR_INVALID_ACCOUNT); |
| 495 return; |
| 496 } |
| 497 |
| 498 if (client_username.empty()) { |
| 499 LOG(ERROR) << "Invalid user name passed in: " << remote_jid; |
| 500 result_callback.Run( |
| 501 protocol::ValidatingAuthenticator::Result::ERROR_INVALID_ACCOUNT); |
| 502 return; |
| 503 } |
| 504 |
525 // Check the client domain policy. | 505 // Check the client domain policy. |
526 if (!required_client_domain_.empty()) { | 506 if (!required_client_domain_.empty()) { |
527 std::string client_username; | |
528 if (!SplitJidResource(remote_jid, &client_username, /*resource=*/nullptr)) { | |
529 LOG(ERROR) << "Rejecting incoming connection from " << remote_jid | |
530 << ": Invalid JID."; | |
531 result_callback.Run(ValidationResult::ERROR_INVALID_ACCOUNT); | |
532 return; | |
533 } | |
534 if (!base::EndsWith(client_username, | 507 if (!base::EndsWith(client_username, |
535 std::string("@") + required_client_domain_, | 508 std::string("@") + required_client_domain_, |
536 base::CompareCase::INSENSITIVE_ASCII)) { | 509 base::CompareCase::INSENSITIVE_ASCII)) { |
537 LOG(ERROR) << "Rejecting incoming connection from " << remote_jid | 510 LOG(ERROR) << "Rejecting incoming connection from " << remote_jid |
538 << ": Domain mismatch."; | 511 << ": Domain mismatch."; |
539 result_callback.Run(ValidationResult::ERROR_INVALID_ACCOUNT); | 512 result_callback.Run(ValidationResult::ERROR_INVALID_ACCOUNT); |
540 return; | 513 return; |
541 } | 514 } |
542 } | 515 } |
543 | 516 |
544 result_callback.Run(ValidationResult::SUCCESS); | 517 // Show a confirmation dialog to the user to allow them to confirm/reject it. |
| 518 std::unique_ptr<It2MeConfirmationDialog> confirmation_dialog = |
| 519 confirmation_dialog_factory_->Create(); |
| 520 |
| 521 // TODO(joedow): Remove this once confirmation dialog exists on all platforms. |
| 522 if (!confirmation_dialog) { |
| 523 result_callback.Run(ValidationResult::SUCCESS); |
| 524 return; |
| 525 } |
| 526 |
| 527 confirmation_dialog_proxy_.reset(new It2MeConfirmationDialogProxy( |
| 528 host_context_->ui_task_runner(), std::move(confirmation_dialog))); |
| 529 |
| 530 confirmation_dialog_proxy_->Show( |
| 531 client_username, base::Bind(&It2MeHost::OnConfirmationResult, |
| 532 base::Unretained(this), result_callback)); |
| 533 } |
| 534 |
| 535 void It2MeHost::OnConfirmationResult( |
| 536 const protocol::ValidatingAuthenticator::ResultCallback& result_callback, |
| 537 It2MeConfirmationDialog::Result result) { |
| 538 switch (result) { |
| 539 case It2MeConfirmationDialog::Result::OK: |
| 540 result_callback.Run(ValidationResult::SUCCESS); |
| 541 break; |
| 542 |
| 543 case It2MeConfirmationDialog::Result::CANCEL: |
| 544 result_callback.Run(ValidationResult::ERROR_REJECTED_BY_USER); |
| 545 break; |
| 546 } |
545 } | 547 } |
546 | 548 |
547 It2MeHostFactory::It2MeHostFactory() {} | 549 It2MeHostFactory::It2MeHostFactory() {} |
548 | 550 |
549 It2MeHostFactory::~It2MeHostFactory() {} | 551 It2MeHostFactory::~It2MeHostFactory() {} |
550 | 552 |
551 scoped_refptr<It2MeHost> It2MeHostFactory::CreateIt2MeHost( | 553 scoped_refptr<It2MeHost> It2MeHostFactory::CreateIt2MeHost( |
552 std::unique_ptr<ChromotingHostContext> context, | 554 std::unique_ptr<ChromotingHostContext> context, |
553 policy::PolicyService* policy_service, | 555 policy::PolicyService* policy_service, |
554 base::WeakPtr<It2MeHost::Observer> observer, | 556 base::WeakPtr<It2MeHost::Observer> observer, |
555 const XmppSignalStrategy::XmppServerConfig& xmpp_server_config, | 557 const XmppSignalStrategy::XmppServerConfig& xmpp_server_config, |
556 const std::string& directory_bot_jid) { | 558 const std::string& directory_bot_jid) { |
557 DCHECK(context->ui_task_runner()->BelongsToCurrentThread()); | 559 DCHECK(context->ui_task_runner()->BelongsToCurrentThread()); |
558 | 560 |
559 std::unique_ptr<It2MeConfirmationDialogFactory> confirmation_dialog_factory( | 561 std::unique_ptr<It2MeConfirmationDialogFactory> confirmation_dialog_factory( |
560 new It2MeConfirmationDialogFactory()); | 562 new It2MeConfirmationDialogFactory()); |
561 std::unique_ptr<PolicyWatcher> policy_watcher = | 563 std::unique_ptr<PolicyWatcher> policy_watcher = |
562 PolicyWatcher::Create(policy_service, context->file_task_runner()); | 564 PolicyWatcher::Create(policy_service, context->file_task_runner()); |
563 return new It2MeHost(std::move(context), std::move(policy_watcher), | 565 return new It2MeHost(std::move(context), std::move(policy_watcher), |
564 std::move(confirmation_dialog_factory), observer, | 566 std::move(confirmation_dialog_factory), observer, |
565 xmpp_server_config, directory_bot_jid); | 567 xmpp_server_config, directory_bot_jid); |
566 } | 568 } |
567 | 569 |
568 } // namespace remoting | 570 } // namespace remoting |
OLD | NEW |