Chromium Code Reviews| 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 <string> | 7 #include <string> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #include "base/callback_helpers.h" | |
| 12 #include "base/json/json_reader.h" | 13 #include "base/json/json_reader.h" |
| 13 #include "base/json/json_writer.h" | 14 #include "base/json/json_writer.h" |
| 14 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 16 #include "base/strings/stringize_macros.h" | 17 #include "base/strings/stringize_macros.h" |
| 17 #include "base/threading/thread.h" | 18 #include "base/threading/thread.h" |
| 19 #include "base/time/time.h" | |
| 18 #include "base/values.h" | 20 #include "base/values.h" |
| 19 #include "build/build_config.h" | 21 #include "build/build_config.h" |
| 22 #include "components/policy/policy_constants.h" | |
| 20 #include "net/base/url_util.h" | 23 #include "net/base/url_util.h" |
| 21 #include "net/url_request/url_request_context_getter.h" | 24 #include "net/url_request/url_request_context_getter.h" |
| 22 #include "remoting/base/auto_thread_task_runner.h" | 25 #include "remoting/base/auto_thread_task_runner.h" |
| 23 #include "remoting/host/chromoting_host_context.h" | 26 #include "remoting/host/chromoting_host_context.h" |
| 24 #include "remoting/host/host_exit_codes.h" | 27 #include "remoting/host/host_exit_codes.h" |
| 28 #include "remoting/host/policy_watcher.h" | |
| 25 #include "remoting/host/service_urls.h" | 29 #include "remoting/host/service_urls.h" |
| 26 #include "remoting/protocol/name_value_map.h" | 30 #include "remoting/protocol/name_value_map.h" |
| 27 | 31 |
| 32 #if defined(OS_WIN) | |
| 33 #include "base/command_line.h" | |
| 34 #include "base/files/file_path.h" | |
| 35 | |
| 36 #include "remoting/host/win/elevated_native_messaging_host.h" | |
| 37 #endif // defined(OS_WIN) | |
| 38 | |
| 28 namespace remoting { | 39 namespace remoting { |
| 29 | 40 |
| 30 namespace { | 41 namespace { |
| 31 | 42 |
| 32 const remoting::protocol::NameMapElement<It2MeHostState> kIt2MeHostStates[] = { | 43 const remoting::protocol::NameMapElement<It2MeHostState> kIt2MeHostStates[] = { |
| 33 {kDisconnected, "DISCONNECTED"}, | 44 {kDisconnected, "DISCONNECTED"}, |
| 34 {kStarting, "STARTING"}, | 45 {kStarting, "STARTING"}, |
| 35 {kRequestedAccessCode, "REQUESTED_ACCESS_CODE"}, | 46 {kRequestedAccessCode, "REQUESTED_ACCESS_CODE"}, |
| 36 {kReceivedAccessCode, "RECEIVED_ACCESS_CODE"}, | 47 {kReceivedAccessCode, "RECEIVED_ACCESS_CODE"}, |
| 37 {kConnected, "CONNECTED"}, | 48 {kConnected, "CONNECTED"}, |
| 38 {kError, "ERROR"}, | 49 {kError, "ERROR"}, |
| 39 {kInvalidDomainError, "INVALID_DOMAIN_ERROR"}, | 50 {kInvalidDomainError, "INVALID_DOMAIN_ERROR"}, |
| 40 }; | 51 }; |
| 41 | 52 |
| 53 #if defined(OS_WIN) | |
| 54 const base::FilePath::CharType kBaseHostBinaryName[] = | |
| 55 FILE_PATH_LITERAL("remote_assistance_host.exe"); | |
| 56 const base::FilePath::CharType kElevatedHostBinaryName[] = | |
| 57 FILE_PATH_LITERAL("remote_assistance_host_uiaccess.exe"); | |
| 58 #endif // defined(OS_WIN) | |
| 59 | |
| 42 } // namespace | 60 } // namespace |
| 43 | 61 |
| 44 It2MeNativeMessagingHost::It2MeNativeMessagingHost( | 62 It2MeNativeMessagingHost::It2MeNativeMessagingHost( |
| 63 bool needs_elevation, | |
| 45 std::unique_ptr<ChromotingHostContext> context, | 64 std::unique_ptr<ChromotingHostContext> context, |
| 46 std::unique_ptr<It2MeHostFactory> factory) | 65 std::unique_ptr<It2MeHostFactory> factory) |
| 47 : client_(nullptr), | 66 : needs_elevation_(needs_elevation), |
| 48 host_context_(std::move(context)), | 67 host_context_(std::move(context)), |
| 49 factory_(std::move(factory)), | 68 factory_(std::move(factory)), |
| 69 policy_watcher_(PolicyWatcher::Create(factory_->get_policy_service(), | |
| 70 host_context_->file_task_runner())), | |
| 50 weak_factory_(this) { | 71 weak_factory_(this) { |
| 51 weak_ptr_ = weak_factory_.GetWeakPtr(); | 72 weak_ptr_ = weak_factory_.GetWeakPtr(); |
| 52 | 73 |
| 53 const ServiceUrls* service_urls = ServiceUrls::GetInstance(); | 74 const ServiceUrls* service_urls = ServiceUrls::GetInstance(); |
| 54 const bool xmpp_server_valid = | 75 const bool xmpp_server_valid = |
| 55 net::ParseHostAndPort(service_urls->xmpp_server_address(), | 76 net::ParseHostAndPort(service_urls->xmpp_server_address(), |
| 56 &xmpp_server_config_.host, | 77 &xmpp_server_config_.host, |
| 57 &xmpp_server_config_.port); | 78 &xmpp_server_config_.port); |
| 58 DCHECK(xmpp_server_valid); | 79 DCHECK(xmpp_server_valid); |
| 59 | 80 |
| 60 xmpp_server_config_.use_tls = service_urls->xmpp_server_use_tls(); | 81 xmpp_server_config_.use_tls = service_urls->xmpp_server_use_tls(); |
| 61 directory_bot_jid_ = service_urls->directory_bot_jid(); | 82 directory_bot_jid_ = service_urls->directory_bot_jid(); |
| 83 | |
| 84 policy_watcher_->StartWatching( | |
| 85 base::Bind(&It2MeNativeMessagingHost::OnPolicyUpdate, | |
| 86 base::Unretained(this)), | |
|
Sergey Ulanov
2016/08/31 23:00:17
I don't think it's safe to use Unretained() here b
joedow
2016/09/02 21:58:59
Done.
| |
| 87 base::Bind(&It2MeNativeMessagingHost::OnPolicyError, | |
| 88 base::Unretained(this))); | |
| 62 } | 89 } |
| 63 | 90 |
| 64 It2MeNativeMessagingHost::~It2MeNativeMessagingHost() { | 91 It2MeNativeMessagingHost::~It2MeNativeMessagingHost() { |
| 65 DCHECK(task_runner()->BelongsToCurrentThread()); | 92 DCHECK(task_runner()->BelongsToCurrentThread()); |
| 66 | 93 |
| 67 if (it2me_host_.get()) { | 94 if (it2me_host_.get()) { |
| 68 it2me_host_->Disconnect(); | 95 it2me_host_->Disconnect(); |
| 69 it2me_host_ = nullptr; | 96 it2me_host_ = nullptr; |
| 70 } | 97 } |
| 71 } | 98 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 92 | 119 |
| 93 std::string type; | 120 std::string type; |
| 94 if (!message_dict->GetString("type", &type)) { | 121 if (!message_dict->GetString("type", &type)) { |
| 95 SendErrorAndExit(std::move(response), "'type' not found in request."); | 122 SendErrorAndExit(std::move(response), "'type' not found in request."); |
| 96 return; | 123 return; |
| 97 } | 124 } |
| 98 | 125 |
| 99 response->SetString("type", type + "Response"); | 126 response->SetString("type", type + "Response"); |
| 100 | 127 |
| 101 if (type == "hello") { | 128 if (type == "hello") { |
| 102 ProcessHello(*message_dict, std::move(response)); | 129 ProcessHello(std::move(message_dict), std::move(response)); |
| 103 } else if (type == "connect") { | 130 } else if (type == "connect") { |
| 104 ProcessConnect(*message_dict, std::move(response)); | 131 ProcessConnect(std::move(message_dict), std::move(response)); |
| 105 } else if (type == "disconnect") { | 132 } else if (type == "disconnect") { |
| 106 ProcessDisconnect(*message_dict, std::move(response)); | 133 ProcessDisconnect(std::move(message_dict), std::move(response)); |
| 107 } else { | 134 } else { |
| 108 SendErrorAndExit(std::move(response), "Unsupported request type: " + type); | 135 SendErrorAndExit(std::move(response), "Unsupported request type: " + type); |
| 109 } | 136 } |
| 110 } | 137 } |
| 111 | 138 |
| 112 void It2MeNativeMessagingHost::Start(Client* client) { | 139 void It2MeNativeMessagingHost::Start(Client* client) { |
| 113 DCHECK(task_runner()->BelongsToCurrentThread()); | 140 DCHECK(task_runner()->BelongsToCurrentThread()); |
| 114 client_ = client; | 141 client_ = client; |
| 115 #if !defined(OS_CHROMEOS) | 142 #if !defined(OS_CHROMEOS) |
| 116 log_message_handler_.reset( | 143 log_message_handler_.reset( |
| 117 new LogMessageHandler( | 144 new LogMessageHandler( |
| 118 base::Bind(&It2MeNativeMessagingHost::SendMessageToClient, | 145 base::Bind(&It2MeNativeMessagingHost::SendMessageToClient, |
| 119 base::Unretained(this)))); | 146 base::Unretained(this)))); |
| 120 #endif // !defined(OS_CHROMEOS) | 147 #endif // !defined(OS_CHROMEOS) |
| 121 } | 148 } |
| 122 | 149 |
| 123 void It2MeNativeMessagingHost::SendMessageToClient( | 150 void It2MeNativeMessagingHost::SendMessageToClient( |
| 124 std::unique_ptr<base::Value> message) const { | 151 std::unique_ptr<base::Value> message) const { |
| 125 DCHECK(task_runner()->BelongsToCurrentThread()); | 152 DCHECK(task_runner()->BelongsToCurrentThread()); |
| 126 std::string message_json; | 153 std::string message_json; |
| 127 base::JSONWriter::Write(*message, &message_json); | 154 base::JSONWriter::Write(*message, &message_json); |
| 128 client_->PostMessageFromNativeHost(message_json); | 155 client_->PostMessageFromNativeHost(message_json); |
| 129 } | 156 } |
| 130 | 157 |
| 131 void It2MeNativeMessagingHost::ProcessHello( | 158 void It2MeNativeMessagingHost::ProcessHello( |
| 132 const base::DictionaryValue& message, | 159 std::unique_ptr<base::DictionaryValue> message, |
| 133 std::unique_ptr<base::DictionaryValue> response) const { | 160 std::unique_ptr<base::DictionaryValue> response) const { |
| 134 DCHECK(task_runner()->BelongsToCurrentThread()); | 161 DCHECK(task_runner()->BelongsToCurrentThread()); |
| 135 | 162 |
| 136 response->SetString("version", STRINGIZE(VERSION)); | 163 response->SetString("version", STRINGIZE(VERSION)); |
| 137 | 164 |
| 138 // This list will be populated when new features are added. | 165 // This list will be populated when new features are added. |
| 139 std::unique_ptr<base::ListValue> supported_features_list( | 166 std::unique_ptr<base::ListValue> supported_features_list( |
| 140 new base::ListValue()); | 167 new base::ListValue()); |
| 141 response->Set("supportedFeatures", supported_features_list.release()); | 168 response->Set("supportedFeatures", supported_features_list.release()); |
| 142 | 169 |
| 143 SendMessageToClient(std::move(response)); | 170 SendMessageToClient(std::move(response)); |
| 144 } | 171 } |
| 145 | 172 |
| 146 void It2MeNativeMessagingHost::ProcessConnect( | 173 void It2MeNativeMessagingHost::ProcessConnect( |
| 147 const base::DictionaryValue& message, | 174 std::unique_ptr<base::DictionaryValue> message, |
| 148 std::unique_ptr<base::DictionaryValue> response) { | 175 std::unique_ptr<base::DictionaryValue> response) { |
| 149 DCHECK(task_runner()->BelongsToCurrentThread()); | 176 DCHECK(task_runner()->BelongsToCurrentThread()); |
| 150 | 177 |
| 178 if (!policy_received_) { | |
| 179 DCHECK(pending_connect_.is_null()); | |
| 180 pending_connect_ = | |
| 181 base::Bind(&It2MeNativeMessagingHost::ProcessConnect, weak_ptr_, | |
| 182 base::Passed(&message), base::Passed(&response)); | |
| 183 return; | |
| 184 } | |
| 185 | |
| 186 if (needs_elevation_ && allow_elevated_host_) { | |
|
Sergey Ulanov
2016/08/31 23:00:16
Add a comment here to explain what happens here.
joedow
2016/09/02 21:58:59
Done.
| |
| 187 if (!DelegateToElevatedHost(std::move(message))) { | |
| 188 response->SetBoolean("result", false); | |
|
Sergey Ulanov
2016/08/31 23:00:16
Does the app support this field right now?
joedow
2016/09/02 21:58:59
I seem to remember testing this in a previous iter
| |
| 189 SendMessageToClient(std::move(response)); | |
| 190 } | |
| 191 return; | |
| 192 } | |
| 193 | |
| 151 if (it2me_host_.get()) { | 194 if (it2me_host_.get()) { |
| 152 SendErrorAndExit(std::move(response), | 195 SendErrorAndExit(std::move(response), |
| 153 "Connect can be called only when disconnected."); | 196 "Connect can be called only when disconnected."); |
| 154 return; | 197 return; |
| 155 } | 198 } |
| 156 | 199 |
| 157 XmppSignalStrategy::XmppServerConfig xmpp_config = xmpp_server_config_; | 200 XmppSignalStrategy::XmppServerConfig xmpp_config = xmpp_server_config_; |
| 158 | 201 |
| 159 if (!message.GetString("userName", &xmpp_config.username)) { | 202 if (!message->GetString("userName", &xmpp_config.username)) { |
| 160 SendErrorAndExit(std::move(response), "'userName' not found in request."); | 203 SendErrorAndExit(std::move(response), "'userName' not found in request."); |
| 161 return; | 204 return; |
| 162 } | 205 } |
| 163 | 206 |
| 164 std::string auth_service_with_token; | 207 std::string auth_service_with_token; |
| 165 if (!message.GetString("authServiceWithToken", &auth_service_with_token)) { | 208 if (!message->GetString("authServiceWithToken", &auth_service_with_token)) { |
| 166 SendErrorAndExit(std::move(response), | 209 SendErrorAndExit(std::move(response), |
| 167 "'authServiceWithToken' not found in request."); | 210 "'authServiceWithToken' not found in request."); |
| 168 return; | 211 return; |
| 169 } | 212 } |
| 170 | 213 |
| 171 // For backward compatibility the webapp still passes OAuth service as part of | 214 // For backward compatibility the webapp still passes OAuth service as part of |
| 172 // the authServiceWithToken field. But auth service part is always expected to | 215 // the authServiceWithToken field. But auth service part is always expected to |
| 173 // be set to oauth2. | 216 // be set to oauth2. |
| 174 const char kOAuth2ServicePrefix[] = "oauth2:"; | 217 const char kOAuth2ServicePrefix[] = "oauth2:"; |
| 175 if (!base::StartsWith(auth_service_with_token, kOAuth2ServicePrefix, | 218 if (!base::StartsWith(auth_service_with_token, kOAuth2ServicePrefix, |
| 176 base::CompareCase::SENSITIVE)) { | 219 base::CompareCase::SENSITIVE)) { |
| 177 SendErrorAndExit(std::move(response), "Invalid 'authServiceWithToken': " + | 220 SendErrorAndExit(std::move(response), "Invalid 'authServiceWithToken': " + |
| 178 auth_service_with_token); | 221 auth_service_with_token); |
| 179 return; | 222 return; |
| 180 } | 223 } |
| 181 | 224 |
| 182 xmpp_config.auth_token = | 225 xmpp_config.auth_token = |
| 183 auth_service_with_token.substr(strlen(kOAuth2ServicePrefix)); | 226 auth_service_with_token.substr(strlen(kOAuth2ServicePrefix)); |
| 184 | 227 |
| 185 #if !defined(NDEBUG) | 228 #if !defined(NDEBUG) |
| 186 std::string address; | 229 std::string address; |
| 187 if (!message.GetString("xmppServerAddress", &address)) { | 230 if (!message->GetString("xmppServerAddress", &address)) { |
| 188 SendErrorAndExit(std::move(response), | 231 SendErrorAndExit(std::move(response), |
| 189 "'xmppServerAddress' not found in request."); | 232 "'xmppServerAddress' not found in request."); |
| 190 return; | 233 return; |
| 191 } | 234 } |
| 192 | 235 |
| 193 if (!net::ParseHostAndPort(address, &xmpp_config.host, | 236 if (!net::ParseHostAndPort(address, &xmpp_config.host, |
| 194 &xmpp_config.port)) { | 237 &xmpp_config.port)) { |
| 195 SendErrorAndExit(std::move(response), | 238 SendErrorAndExit(std::move(response), |
| 196 "Invalid 'xmppServerAddress': " + address); | 239 "Invalid 'xmppServerAddress': " + address); |
| 197 return; | 240 return; |
| 198 } | 241 } |
| 199 | 242 |
| 200 if (!message.GetBoolean("xmppServerUseTls", &xmpp_config.use_tls)) { | 243 if (!message->GetBoolean("xmppServerUseTls", &xmpp_config.use_tls)) { |
| 201 SendErrorAndExit(std::move(response), | 244 SendErrorAndExit(std::move(response), |
| 202 "'xmppServerUseTls' not found in request."); | 245 "'xmppServerUseTls' not found in request."); |
| 203 return; | 246 return; |
| 204 } | 247 } |
| 205 | 248 |
| 206 if (!message.GetString("directoryBotJid", &directory_bot_jid_)) { | 249 if (!message->GetString("directoryBotJid", &directory_bot_jid_)) { |
| 207 SendErrorAndExit(std::move(response), | 250 SendErrorAndExit(std::move(response), |
| 208 "'directoryBotJid' not found in request."); | 251 "'directoryBotJid' not found in request."); |
| 209 return; | 252 return; |
| 210 } | 253 } |
| 211 #endif // !defined(NDEBUG) | 254 #endif // !defined(NDEBUG) |
| 212 | 255 |
| 213 // Create the It2Me host and start connecting. | 256 // Create the It2Me host and start connecting. |
| 214 it2me_host_ = factory_->CreateIt2MeHost(host_context_->Copy(), | 257 it2me_host_ = factory_->CreateIt2MeHost(host_context_->Copy(), |
| 215 weak_ptr_, | 258 weak_ptr_, |
| 216 xmpp_config, | 259 xmpp_config, |
| 217 directory_bot_jid_); | 260 directory_bot_jid_); |
| 218 it2me_host_->Connect(); | 261 it2me_host_->Connect(); |
| 219 | 262 |
| 220 SendMessageToClient(std::move(response)); | 263 SendMessageToClient(std::move(response)); |
| 221 } | 264 } |
| 222 | 265 |
| 223 void It2MeNativeMessagingHost::ProcessDisconnect( | 266 void It2MeNativeMessagingHost::ProcessDisconnect( |
| 224 const base::DictionaryValue& message, | 267 std::unique_ptr<base::DictionaryValue> message, |
| 225 std::unique_ptr<base::DictionaryValue> response) { | 268 std::unique_ptr<base::DictionaryValue> response) { |
| 226 DCHECK(task_runner()->BelongsToCurrentThread()); | 269 DCHECK(task_runner()->BelongsToCurrentThread()); |
| 270 DCHECK(policy_received_); | |
| 271 | |
| 272 if (needs_elevation_ && allow_elevated_host_) { | |
| 273 if (!DelegateToElevatedHost(std::move(message))) { | |
| 274 response->SetBoolean("result", false); | |
| 275 SendMessageToClient(std::move(response)); | |
| 276 } | |
| 277 return; | |
| 278 } | |
| 227 | 279 |
| 228 if (it2me_host_.get()) { | 280 if (it2me_host_.get()) { |
| 229 it2me_host_->Disconnect(); | 281 it2me_host_->Disconnect(); |
| 230 it2me_host_ = nullptr; | 282 it2me_host_ = nullptr; |
| 231 } | 283 } |
| 232 SendMessageToClient(std::move(response)); | 284 SendMessageToClient(std::move(response)); |
| 233 } | 285 } |
| 234 | 286 |
| 235 void It2MeNativeMessagingHost::SendErrorAndExit( | 287 void It2MeNativeMessagingHost::SendErrorAndExit( |
| 236 std::unique_ptr<base::DictionaryValue> response, | 288 std::unique_ptr<base::DictionaryValue> response, |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 321 It2MeNativeMessagingHost::task_runner() const { | 373 It2MeNativeMessagingHost::task_runner() const { |
| 322 return host_context_->ui_task_runner(); | 374 return host_context_->ui_task_runner(); |
| 323 } | 375 } |
| 324 | 376 |
| 325 /* static */ | 377 /* static */ |
| 326 std::string It2MeNativeMessagingHost::HostStateToString( | 378 std::string It2MeNativeMessagingHost::HostStateToString( |
| 327 It2MeHostState host_state) { | 379 It2MeHostState host_state) { |
| 328 return ValueToName(kIt2MeHostStates, host_state); | 380 return ValueToName(kIt2MeHostStates, host_state); |
| 329 } | 381 } |
| 330 | 382 |
| 383 void It2MeNativeMessagingHost::OnPolicyUpdate( | |
| 384 std::unique_ptr<base::DictionaryValue> policies) { | |
| 385 // The policy watcher runs on the |file_task_runner| but we want to run the | |
| 386 // update code on |task_runner|. | |
| 387 if (!task_runner()->BelongsToCurrentThread()) { | |
| 388 task_runner()->PostTask( | |
| 389 FROM_HERE, base::Bind(&It2MeNativeMessagingHost::OnPolicyUpdate, | |
| 390 weak_ptr_, base::Passed(&policies))); | |
| 391 return; | |
| 392 } | |
| 393 | |
| 394 if (policy_received_) { | |
| 395 // Don't dynamically change how the host operates since we don't have a good | |
| 396 // way to communicate changes to the user. | |
| 397 return; | |
| 398 } | |
| 399 | |
| 400 if (!policies->GetBoolean( | |
| 401 policy::key::kRemoteAccessHostAllowUiAccessForRemoteAssistance, | |
| 402 &allow_elevated_host_)) { | |
| 403 LOG(WARNING) << "Failed to retrieve elevated host policy value."; | |
| 404 } | |
| 405 | |
| 406 policy_received_ = true; | |
| 407 if (!pending_connect_.is_null()) { | |
| 408 base::ResetAndReturn(&pending_connect_).Run(); | |
| 409 } | |
| 410 } | |
| 411 | |
| 412 void It2MeNativeMessagingHost::OnPolicyError() { | |
| 413 // TODO(joedow): Report the policy error to the user. crbug.com/433009 | |
| 414 NOTIMPLEMENTED(); | |
| 415 } | |
| 416 | |
| 417 #if defined(OS_WIN) | |
| 418 | |
| 419 bool It2MeNativeMessagingHost::DelegateToElevatedHost( | |
| 420 std::unique_ptr<base::DictionaryValue> message) { | |
| 421 DCHECK(task_runner()->BelongsToCurrentThread()); | |
| 422 DCHECK(needs_elevation_); | |
| 423 DCHECK(allow_elevated_host_); | |
| 424 | |
| 425 if (!elevated_host_) { | |
| 426 base::FilePath binary_path = | |
| 427 base::CommandLine::ForCurrentProcess()->GetProgram(); | |
| 428 CHECK(binary_path.BaseName() == base::FilePath(kBaseHostBinaryName)); | |
| 429 | |
| 430 // The new process runs at an elevated level due to being granted uiAccess. | |
| 431 elevated_host_.reset(new ElevatedNativeMessagingHost( | |
| 432 binary_path.DirName().Append(kElevatedHostBinaryName), | |
| 433 /*parent_window_handle=*/0, | |
|
Sergey Ulanov
2016/08/31 23:00:17
Why is this not parameter passed to the elevated p
joedow
2016/09/02 21:58:59
Done.
| |
| 434 /*elevate_process=*/false, | |
| 435 /*host_timeout=*/base::TimeDelta(), client_)); | |
| 436 } | |
| 437 | |
| 438 if (elevated_host_->EnsureElevatedHostCreated()) { | |
| 439 elevated_host_->SendMessage(std::move(message)); | |
| 440 return true; | |
| 441 } | |
| 442 | |
| 443 return false; | |
| 444 } | |
| 445 | |
| 446 #else // !defined(OS_WIN) | |
| 447 | |
| 448 bool It2MeNativeMessagingHost::DelegateToElevatedHost( | |
| 449 std::unique_ptr<base::DictionaryValue> message) { | |
| 450 NOTREACHED(); | |
| 451 return false; | |
| 452 } | |
| 453 | |
| 454 #endif // !defined(OS_WIN) | |
| 455 | |
| 331 } // namespace remoting | 456 } // namespace remoting |
| OLD | NEW |