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 |