| 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_native_messaging_host.h" | 5 #include "remoting/host/it2me/it2me_native_messaging_host.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/callback.h" | 12 #include "base/callback.h" |
| 13 #include "base/callback_helpers.h" | 13 #include "base/callback_helpers.h" |
| 14 #include "base/json/json_reader.h" | 14 #include "base/json/json_reader.h" |
| 15 #include "base/json/json_writer.h" | 15 #include "base/json/json_writer.h" |
| 16 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 17 #include "base/strings/string_util.h" | 17 #include "base/strings/string_util.h" |
| 18 #include "base/strings/stringize_macros.h" | 18 #include "base/strings/stringize_macros.h" |
| 19 #include "base/threading/thread.h" | 19 #include "base/threading/thread.h" |
| 20 #include "base/time/time.h" | 20 #include "base/time/time.h" |
| 21 #include "base/values.h" | 21 #include "base/values.h" |
| 22 #include "build/build_config.h" | 22 #include "build/build_config.h" |
| 23 #include "components/policy/policy_constants.h" | 23 #include "components/policy/policy_constants.h" |
| 24 #include "net/base/url_util.h" | 24 #include "net/base/url_util.h" |
| 25 #include "net/socket/client_socket_factory.h" |
| 25 #include "net/url_request/url_request_context_getter.h" | 26 #include "net/url_request/url_request_context_getter.h" |
| 26 #include "remoting/base/auto_thread_task_runner.h" | 27 #include "remoting/base/auto_thread_task_runner.h" |
| 27 #include "remoting/host/chromoting_host_context.h" | 28 #include "remoting/host/chromoting_host_context.h" |
| 28 #include "remoting/host/host_exit_codes.h" | 29 #include "remoting/host/host_exit_codes.h" |
| 29 #include "remoting/host/policy_watcher.h" | 30 #include "remoting/host/policy_watcher.h" |
| 30 #include "remoting/host/service_urls.h" | 31 #include "remoting/host/service_urls.h" |
| 31 #include "remoting/protocol/name_value_map.h" | 32 #include "remoting/protocol/name_value_map.h" |
| 33 #include "remoting/signaling/delegating_signal_strategy.h" |
| 32 | 34 |
| 33 #if defined(OS_WIN) | 35 #if defined(OS_WIN) |
| 34 #include "base/command_line.h" | 36 #include "base/command_line.h" |
| 35 #include "base/files/file_path.h" | 37 #include "base/files/file_path.h" |
| 36 | 38 |
| 37 #include "remoting/host/win/elevated_native_messaging_host.h" | 39 #include "remoting/host/win/elevated_native_messaging_host.h" |
| 38 #endif // defined(OS_WIN) | 40 #endif // defined(OS_WIN) |
| 39 | 41 |
| 40 namespace remoting { | 42 namespace remoting { |
| 41 | 43 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 std::unique_ptr<It2MeHostFactory> factory) | 87 std::unique_ptr<It2MeHostFactory> factory) |
| 86 : needs_elevation_(needs_elevation), | 88 : needs_elevation_(needs_elevation), |
| 87 host_context_(std::move(context)), | 89 host_context_(std::move(context)), |
| 88 factory_(std::move(factory)), | 90 factory_(std::move(factory)), |
| 89 policy_service_(policy_service), | 91 policy_service_(policy_service), |
| 90 policy_watcher_(PolicyWatcher::Create(policy_service_, | 92 policy_watcher_(PolicyWatcher::Create(policy_service_, |
| 91 host_context_->file_task_runner())), | 93 host_context_->file_task_runner())), |
| 92 weak_factory_(this) { | 94 weak_factory_(this) { |
| 93 weak_ptr_ = weak_factory_.GetWeakPtr(); | 95 weak_ptr_ = weak_factory_.GetWeakPtr(); |
| 94 | 96 |
| 95 const ServiceUrls* service_urls = ServiceUrls::GetInstance(); | |
| 96 const bool xmpp_server_valid = | |
| 97 net::ParseHostAndPort(service_urls->xmpp_server_address(), | |
| 98 &xmpp_server_config_.host, | |
| 99 &xmpp_server_config_.port); | |
| 100 DCHECK(xmpp_server_valid); | |
| 101 | |
| 102 xmpp_server_config_.use_tls = service_urls->xmpp_server_use_tls(); | |
| 103 directory_bot_jid_ = service_urls->directory_bot_jid(); | |
| 104 | |
| 105 // The policy watcher runs on the |file_task_runner| but we want to run the | 97 // The policy watcher runs on the |file_task_runner| but we want to run the |
| 106 // update code on |task_runner| so we use a shim to post the callback to the | 98 // update code on |task_runner| so we use a shim to post the callback to the |
| 107 // preferred task runner. | 99 // preferred task runner. |
| 108 PolicyWatcher::PolicyUpdatedCallback update_callback = | 100 PolicyWatcher::PolicyUpdatedCallback update_callback = |
| 109 base::Bind(&It2MeNativeMessagingHost::OnPolicyUpdate, weak_ptr_); | 101 base::Bind(&It2MeNativeMessagingHost::OnPolicyUpdate, weak_ptr_); |
| 110 policy_watcher_->StartWatching( | 102 policy_watcher_->StartWatching( |
| 111 base::Bind(&PolicyUpdateCallback, task_runner(), update_callback), | 103 base::Bind(&PolicyUpdateCallback, task_runner(), update_callback), |
| 112 base::Bind(&OnPolicyError)); | 104 base::Bind(&OnPolicyError)); |
| 113 } | 105 } |
| 114 | 106 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 } | 140 } |
| 149 | 141 |
| 150 response->SetString("type", type + "Response"); | 142 response->SetString("type", type + "Response"); |
| 151 | 143 |
| 152 if (type == "hello") { | 144 if (type == "hello") { |
| 153 ProcessHello(std::move(message_dict), std::move(response)); | 145 ProcessHello(std::move(message_dict), std::move(response)); |
| 154 } else if (type == "connect") { | 146 } else if (type == "connect") { |
| 155 ProcessConnect(std::move(message_dict), std::move(response)); | 147 ProcessConnect(std::move(message_dict), std::move(response)); |
| 156 } else if (type == "disconnect") { | 148 } else if (type == "disconnect") { |
| 157 ProcessDisconnect(std::move(message_dict), std::move(response)); | 149 ProcessDisconnect(std::move(message_dict), std::move(response)); |
| 150 } else if (type == "incomingIq") { |
| 151 ProcessIncomingIq(std::move(message_dict), std::move(response)); |
| 158 } else { | 152 } else { |
| 159 SendErrorAndExit(std::move(response), "Unsupported request type: " + type); | 153 SendErrorAndExit(std::move(response), "Unsupported request type: " + type); |
| 160 } | 154 } |
| 161 } | 155 } |
| 162 | 156 |
| 163 void It2MeNativeMessagingHost::Start(Client* client) { | 157 void It2MeNativeMessagingHost::Start(Client* client) { |
| 164 DCHECK(task_runner()->BelongsToCurrentThread()); | 158 DCHECK(task_runner()->BelongsToCurrentThread()); |
| 165 client_ = client; | 159 client_ = client; |
| 166 #if !defined(OS_CHROMEOS) | 160 #if !defined(OS_CHROMEOS) |
| 167 log_message_handler_.reset( | 161 log_message_handler_.reset( |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 } | 213 } |
| 220 return; | 214 return; |
| 221 } | 215 } |
| 222 | 216 |
| 223 if (it2me_host_.get()) { | 217 if (it2me_host_.get()) { |
| 224 SendErrorAndExit(std::move(response), | 218 SendErrorAndExit(std::move(response), |
| 225 "Connect can be called only when disconnected."); | 219 "Connect can be called only when disconnected."); |
| 226 return; | 220 return; |
| 227 } | 221 } |
| 228 | 222 |
| 229 XmppSignalStrategy::XmppServerConfig xmpp_config = xmpp_server_config_; | 223 std::string username; |
| 230 | 224 if (!message->GetString("userName", &username)) { |
| 231 if (!message->GetString("userName", &xmpp_config.username)) { | |
| 232 SendErrorAndExit(std::move(response), "'userName' not found in request."); | 225 SendErrorAndExit(std::move(response), "'userName' not found in request."); |
| 233 return; | 226 return; |
| 234 } | 227 } |
| 235 | 228 |
| 236 std::string auth_service_with_token; | 229 bool use_signaling_proxy = false; |
| 237 if (!message->GetString("authServiceWithToken", &auth_service_with_token)) { | 230 message->GetBoolean("useSignalingProxy", &use_signaling_proxy); |
| 238 SendErrorAndExit(std::move(response), | 231 |
| 239 "'authServiceWithToken' not found in request."); | 232 const ServiceUrls* service_urls = ServiceUrls::GetInstance(); |
| 240 return; | 233 std::unique_ptr<SignalStrategy> signal_strategy; |
| 234 |
| 235 if (!use_signaling_proxy) { |
| 236 XmppSignalStrategy::XmppServerConfig xmpp_config; |
| 237 xmpp_config.username = username; |
| 238 |
| 239 const bool xmpp_server_valid = |
| 240 net::ParseHostAndPort(service_urls->xmpp_server_address(), |
| 241 &xmpp_config.host, &xmpp_config.port); |
| 242 DCHECK(xmpp_server_valid); |
| 243 xmpp_config.use_tls = service_urls->xmpp_server_use_tls(); |
| 244 |
| 245 std::string auth_service_with_token; |
| 246 if (!message->GetString("authServiceWithToken", &auth_service_with_token)) { |
| 247 SendErrorAndExit(std::move(response), |
| 248 "'authServiceWithToken' not found in request."); |
| 249 return; |
| 250 } |
| 251 |
| 252 // For backward compatibility the webapp still passes OAuth service as part |
| 253 // of the authServiceWithToken field. But auth service part is always |
| 254 // expected to be set to oauth2. |
| 255 const char kOAuth2ServicePrefix[] = "oauth2:"; |
| 256 if (!base::StartsWith(auth_service_with_token, kOAuth2ServicePrefix, |
| 257 base::CompareCase::SENSITIVE)) { |
| 258 SendErrorAndExit(std::move(response), "Invalid 'authServiceWithToken': " + |
| 259 auth_service_with_token); |
| 260 return; |
| 261 } |
| 262 |
| 263 xmpp_config.auth_token = |
| 264 auth_service_with_token.substr(strlen(kOAuth2ServicePrefix)); |
| 265 |
| 266 #if !defined(NDEBUG) |
| 267 std::string address; |
| 268 if (!message->GetString("xmppServerAddress", &address)) { |
| 269 SendErrorAndExit(std::move(response), |
| 270 "'xmppServerAddress' not found in request."); |
| 271 return; |
| 272 } |
| 273 |
| 274 if (!net::ParseHostAndPort(address, &xmpp_config.host, &xmpp_config.port)) { |
| 275 SendErrorAndExit(std::move(response), |
| 276 "Invalid 'xmppServerAddress': " + address); |
| 277 return; |
| 278 } |
| 279 |
| 280 if (!message->GetBoolean("xmppServerUseTls", &xmpp_config.use_tls)) { |
| 281 SendErrorAndExit(std::move(response), |
| 282 "'xmppServerUseTls' not found in request."); |
| 283 return; |
| 284 } |
| 285 #endif // !defined(NDEBUG) |
| 286 |
| 287 signal_strategy.reset(new XmppSignalStrategy( |
| 288 net::ClientSocketFactory::GetDefaultFactory(), |
| 289 host_context_->url_request_context_getter(), xmpp_config)); |
| 290 } else { |
| 291 std::string local_jid; |
| 292 |
| 293 if (!message->GetString("localJid", &local_jid)) { |
| 294 SendErrorAndExit(std::move(response), "'localJid' not found in request."); |
| 295 return; |
| 296 } |
| 297 |
| 298 delegating_signal_strategy_ = new DelegatingSignalStrategy( |
| 299 local_jid, host_context_->network_task_runner(), |
| 300 base::Bind(&It2MeNativeMessagingHost::SendOutgoingIq, |
| 301 weak_factory_.GetWeakPtr())); |
| 302 signal_strategy.reset(delegating_signal_strategy_); |
| 241 } | 303 } |
| 242 | 304 |
| 243 // For backward compatibility the webapp still passes OAuth service as part of | 305 std::string directory_bot_jid = service_urls->directory_bot_jid(); |
| 244 // the authServiceWithToken field. But auth service part is always expected to | |
| 245 // be set to oauth2. | |
| 246 const char kOAuth2ServicePrefix[] = "oauth2:"; | |
| 247 if (!base::StartsWith(auth_service_with_token, kOAuth2ServicePrefix, | |
| 248 base::CompareCase::SENSITIVE)) { | |
| 249 SendErrorAndExit(std::move(response), "Invalid 'authServiceWithToken': " + | |
| 250 auth_service_with_token); | |
| 251 return; | |
| 252 } | |
| 253 | |
| 254 xmpp_config.auth_token = | |
| 255 auth_service_with_token.substr(strlen(kOAuth2ServicePrefix)); | |
| 256 | 306 |
| 257 #if !defined(NDEBUG) | 307 #if !defined(NDEBUG) |
| 258 std::string address; | 308 if (!message->GetString("directoryBotJid", &directory_bot_jid)) { |
| 259 if (!message->GetString("xmppServerAddress", &address)) { | |
| 260 SendErrorAndExit(std::move(response), | |
| 261 "'xmppServerAddress' not found in request."); | |
| 262 return; | |
| 263 } | |
| 264 | |
| 265 if (!net::ParseHostAndPort(address, &xmpp_config.host, | |
| 266 &xmpp_config.port)) { | |
| 267 SendErrorAndExit(std::move(response), | |
| 268 "Invalid 'xmppServerAddress': " + address); | |
| 269 return; | |
| 270 } | |
| 271 | |
| 272 if (!message->GetBoolean("xmppServerUseTls", &xmpp_config.use_tls)) { | |
| 273 SendErrorAndExit(std::move(response), | |
| 274 "'xmppServerUseTls' not found in request."); | |
| 275 return; | |
| 276 } | |
| 277 | |
| 278 if (!message->GetString("directoryBotJid", &directory_bot_jid_)) { | |
| 279 SendErrorAndExit(std::move(response), | 309 SendErrorAndExit(std::move(response), |
| 280 "'directoryBotJid' not found in request."); | 310 "'directoryBotJid' not found in request."); |
| 281 return; | 311 return; |
| 282 } | 312 } |
| 283 #endif // !defined(NDEBUG) | 313 #endif // !defined(NDEBUG) |
| 284 | 314 |
| 285 // Create the It2Me host and start connecting. | 315 // Create the It2Me host and start connecting. |
| 286 it2me_host_ = | 316 it2me_host_ = factory_->CreateIt2MeHost( |
| 287 factory_->CreateIt2MeHost(host_context_->Copy(), policy_service_, | 317 host_context_->Copy(), policy_service_, weak_ptr_, |
| 288 weak_ptr_, xmpp_config, directory_bot_jid_); | 318 std::move(signal_strategy), username, directory_bot_jid); |
| 289 it2me_host_->Connect(); | 319 it2me_host_->Connect(); |
| 290 | 320 |
| 291 SendMessageToClient(std::move(response)); | 321 SendMessageToClient(std::move(response)); |
| 292 } | 322 } |
| 293 | 323 |
| 294 void It2MeNativeMessagingHost::ProcessDisconnect( | 324 void It2MeNativeMessagingHost::ProcessDisconnect( |
| 295 std::unique_ptr<base::DictionaryValue> message, | 325 std::unique_ptr<base::DictionaryValue> message, |
| 296 std::unique_ptr<base::DictionaryValue> response) { | 326 std::unique_ptr<base::DictionaryValue> response) { |
| 297 DCHECK(task_runner()->BelongsToCurrentThread()); | 327 DCHECK(task_runner()->BelongsToCurrentThread()); |
| 298 DCHECK(policy_received_); | 328 DCHECK(policy_received_); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 310 return; | 340 return; |
| 311 } | 341 } |
| 312 | 342 |
| 313 if (it2me_host_.get()) { | 343 if (it2me_host_.get()) { |
| 314 it2me_host_->Disconnect(); | 344 it2me_host_->Disconnect(); |
| 315 it2me_host_ = nullptr; | 345 it2me_host_ = nullptr; |
| 316 } | 346 } |
| 317 SendMessageToClient(std::move(response)); | 347 SendMessageToClient(std::move(response)); |
| 318 } | 348 } |
| 319 | 349 |
| 350 void It2MeNativeMessagingHost::ProcessIncomingIq( |
| 351 std::unique_ptr<base::DictionaryValue> message, |
| 352 std::unique_ptr<base::DictionaryValue> response) { |
| 353 std::string iq; |
| 354 if (!message->GetString("iq", &iq)) { |
| 355 LOG(ERROR) << "Invalid incomingIq() data."; |
| 356 return; |
| 357 } |
| 358 |
| 359 if (delegating_signal_strategy_) |
| 360 delegating_signal_strategy_->OnIncomingMessage(iq); |
| 361 SendMessageToClient(std::move(response)); |
| 362 }; |
| 363 |
| 364 void It2MeNativeMessagingHost::SendOutgoingIq(const std::string& iq) { |
| 365 std::unique_ptr<base::DictionaryValue> message(new base::DictionaryValue()); |
| 366 message->SetString("iq", iq); |
| 367 message->SetString("type", "sendOutgoingIq"); |
| 368 SendMessageToClient(std::move(message)); |
| 369 } |
| 370 |
| 320 void It2MeNativeMessagingHost::SendErrorAndExit( | 371 void It2MeNativeMessagingHost::SendErrorAndExit( |
| 321 std::unique_ptr<base::DictionaryValue> response, | 372 std::unique_ptr<base::DictionaryValue> response, |
| 322 const std::string& description) const { | 373 const std::string& description) const { |
| 323 DCHECK(task_runner()->BelongsToCurrentThread()); | 374 DCHECK(task_runner()->BelongsToCurrentThread()); |
| 324 | 375 |
| 325 LOG(ERROR) << description; | 376 LOG(ERROR) << description; |
| 326 | 377 |
| 327 response->SetString("type", "error"); | 378 response->SetString("type", "error"); |
| 328 response->SetString("description", description); | 379 response->SetString("description", description); |
| 329 SendMessageToClient(std::move(response)); | 380 SendMessageToClient(std::move(response)); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 | 527 |
| 477 bool It2MeNativeMessagingHost::DelegateToElevatedHost( | 528 bool It2MeNativeMessagingHost::DelegateToElevatedHost( |
| 478 std::unique_ptr<base::DictionaryValue> message) { | 529 std::unique_ptr<base::DictionaryValue> message) { |
| 479 NOTREACHED(); | 530 NOTREACHED(); |
| 480 return false; | 531 return false; |
| 481 } | 532 } |
| 482 | 533 |
| 483 #endif // !defined(OS_WIN) | 534 #endif // !defined(OS_WIN) |
| 484 | 535 |
| 485 } // namespace remoting | 536 } // namespace remoting |
| OLD | NEW |