| 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/setup/native_messaging_host.h" | 5 #include "remoting/host/setup/native_messaging_host.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/json/json_reader.h" | |
| 12 #include "base/json/json_writer.h" | |
| 13 #include "base/location.h" | 11 #include "base/location.h" |
| 14 #include "base/strings/stringize_macros.h" | 12 #include "base/strings/stringize_macros.h" |
| 15 #include "base/thread_task_runner_handle.h" | 13 #include "base/thread_task_runner_handle.h" |
| 16 #include "base/values.h" | 14 #include "base/values.h" |
| 17 #include "net/base/net_util.h" | 15 #include "net/base/net_util.h" |
| 18 #include "remoting/base/rsa_key_pair.h" | 16 #include "remoting/base/rsa_key_pair.h" |
| 19 #include "remoting/host/pin_hash.h" | 17 #include "remoting/host/pin_hash.h" |
| 20 | 18 |
| 21 namespace { | 19 namespace { |
| 22 | 20 |
| 23 // Helper to extract the "config" part of a message as a DictionaryValue. | 21 // Helper to extract the "config" part of a message as a DictionaryValue. |
| 24 // Returns NULL on failure, and logs an error message. | 22 // Returns NULL on failure, and logs an error message. |
| 25 scoped_ptr<base::DictionaryValue> ConfigDictionaryFromMessage( | 23 scoped_ptr<base::DictionaryValue> ConfigDictionaryFromMessage( |
| 26 const base::DictionaryValue& message) { | 24 const base::DictionaryValue& message) { |
| 27 scoped_ptr<base::DictionaryValue> config_dict; | 25 scoped_ptr<base::DictionaryValue> result; |
| 28 std::string config_str; | 26 const base::DictionaryValue* config_dict; |
| 29 if (!message.GetString("config", &config_str)) { | 27 if (message.GetDictionary("config", &config_dict)) { |
| 30 LOG(ERROR) << "'config' not found."; | 28 result.reset(config_dict->DeepCopy()); |
| 31 return config_dict.Pass(); | 29 } else { |
| 30 LOG(ERROR) << "'config' dictionary not found"; |
| 32 } | 31 } |
| 33 | 32 return result.Pass(); |
| 34 // TODO(lambroslambrou): Fix the webapp to embed the config dictionary | |
| 35 // directly into the request, rather than as a serialized JSON string. | |
| 36 scoped_ptr<base::Value> config( | |
| 37 base::JSONReader::Read(config_str, base::JSON_ALLOW_TRAILING_COMMAS)); | |
| 38 if (!config || !config->IsType(base::Value::TYPE_DICTIONARY)) { | |
| 39 LOG(ERROR) << "Bad config parameter."; | |
| 40 return config_dict.Pass(); | |
| 41 } | |
| 42 config_dict.reset(reinterpret_cast<base::DictionaryValue*>(config.release())); | |
| 43 return config_dict.Pass(); | |
| 44 } | 33 } |
| 45 | 34 |
| 46 } // namespace | 35 } // namespace |
| 47 | 36 |
| 48 namespace remoting { | 37 namespace remoting { |
| 49 | 38 |
| 50 NativeMessagingHost::NativeMessagingHost( | 39 NativeMessagingHost::NativeMessagingHost( |
| 51 base::PlatformFile input, | 40 base::PlatformFile input, |
| 52 base::PlatformFile output, | 41 base::PlatformFile output, |
| 53 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, | 42 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
| 54 const base::Closure& quit_closure) | 43 const base::Closure& quit_closure) |
| 55 : caller_task_runner_(caller_task_runner), | 44 : caller_task_runner_(caller_task_runner), |
| 56 quit_closure_(quit_closure), | 45 quit_closure_(quit_closure), |
| 57 native_messaging_reader_(input), | 46 native_messaging_reader_(input), |
| 58 native_messaging_writer_(output), | 47 native_messaging_writer_(output), |
| 59 daemon_controller_(DaemonController::Create()), | 48 daemon_controller_(DaemonController::Create()), |
| 60 weak_factory_(this) { | 49 weak_factory_(this) { |
| 61 weak_ptr_ = weak_factory_.GetWeakPtr(); | 50 weak_ptr_ = weak_factory_.GetWeakPtr(); |
| 62 } | 51 } |
| 63 | 52 |
| 64 NativeMessagingHost::~NativeMessagingHost() { | 53 NativeMessagingHost::~NativeMessagingHost() {} |
| 65 } | |
| 66 | 54 |
| 67 void NativeMessagingHost::Start() { | 55 void NativeMessagingHost::Start() { |
| 68 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 56 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 69 | 57 |
| 70 native_messaging_reader_.Start( | 58 native_messaging_reader_.Start( |
| 71 base::Bind(&NativeMessagingHost::ProcessMessage, weak_ptr_), | 59 base::Bind(&NativeMessagingHost::ProcessMessage, weak_ptr_), |
| 72 base::Bind(&NativeMessagingHost::Shutdown, weak_ptr_)); | 60 base::Bind(&NativeMessagingHost::Shutdown, weak_ptr_)); |
| 73 } | 61 } |
| 74 | 62 |
| 75 void NativeMessagingHost::Shutdown() { | 63 void NativeMessagingHost::Shutdown() { |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 daemon_controller_->UpdateConfig( | 179 daemon_controller_->UpdateConfig( |
| 192 config_dict.Pass(), | 180 config_dict.Pass(), |
| 193 base::Bind(&NativeMessagingHost::SendAsyncResult, base::Unretained(this), | 181 base::Bind(&NativeMessagingHost::SendAsyncResult, base::Unretained(this), |
| 194 base::Passed(&response))); | 182 base::Passed(&response))); |
| 195 return true; | 183 return true; |
| 196 } | 184 } |
| 197 | 185 |
| 198 bool NativeMessagingHost::ProcessGetDaemonConfig( | 186 bool NativeMessagingHost::ProcessGetDaemonConfig( |
| 199 const base::DictionaryValue& message, | 187 const base::DictionaryValue& message, |
| 200 scoped_ptr<base::DictionaryValue> response) { | 188 scoped_ptr<base::DictionaryValue> response) { |
| 201 daemon_controller_->GetConfig(base::Bind( | 189 daemon_controller_->GetConfig( |
| 202 &NativeMessagingHost::SendConfigResponse, | 190 base::Bind(&NativeMessagingHost::SendConfigResponse, |
| 203 base::Unretained(this), base::Passed(&response))); | 191 base::Unretained(this), base::Passed(&response))); |
| 204 return true; | 192 return true; |
| 205 } | 193 } |
| 206 | 194 |
| 207 bool NativeMessagingHost::ProcessGetUsageStatsConsent( | 195 bool NativeMessagingHost::ProcessGetUsageStatsConsent( |
| 208 const base::DictionaryValue& message, | 196 const base::DictionaryValue& message, |
| 209 scoped_ptr<base::DictionaryValue> response) { | 197 scoped_ptr<base::DictionaryValue> response) { |
| 210 daemon_controller_->GetUsageStatsConsent(base::Bind( | 198 daemon_controller_->GetUsageStatsConsent( |
| 211 &NativeMessagingHost::SendUsageStatsConsentResponse, | 199 base::Bind(&NativeMessagingHost::SendUsageStatsConsentResponse, |
| 212 base::Unretained(this), base::Passed(&response))); | 200 base::Unretained(this), base::Passed(&response))); |
| 213 return true; | 201 return true; |
| 214 } | 202 } |
| 215 | 203 |
| 216 bool NativeMessagingHost::ProcessStartDaemon( | 204 bool NativeMessagingHost::ProcessStartDaemon( |
| 217 const base::DictionaryValue& message, | 205 const base::DictionaryValue& message, |
| 218 scoped_ptr<base::DictionaryValue> response) { | 206 scoped_ptr<base::DictionaryValue> response) { |
| 219 bool consent; | 207 bool consent; |
| 220 if (!message.GetBoolean("consent", &consent)) { | 208 if (!message.GetBoolean("consent", &consent)) { |
| 221 LOG(ERROR) << "'consent' not found."; | 209 LOG(ERROR) << "'consent' not found."; |
| 222 return false; | 210 return false; |
| 223 } | 211 } |
| 224 | 212 |
| 225 scoped_ptr<base::DictionaryValue> config_dict = | 213 scoped_ptr<base::DictionaryValue> config_dict = |
| 226 ConfigDictionaryFromMessage(message); | 214 ConfigDictionaryFromMessage(message); |
| 227 if (!config_dict) | 215 if (!config_dict) |
| 228 return false; | 216 return false; |
| 229 | 217 |
| 230 daemon_controller_->SetConfigAndStart( | 218 daemon_controller_->SetConfigAndStart( |
| 231 config_dict.Pass(), consent, | 219 config_dict.Pass(), consent, |
| 232 base::Bind(&NativeMessagingHost::SendAsyncResult, base::Unretained(this), | 220 base::Bind(&NativeMessagingHost::SendAsyncResult, base::Unretained(this), |
| 233 base::Passed(&response))); | 221 base::Passed(&response))); |
| 234 return true; | 222 return true; |
| 235 } | 223 } |
| 236 | 224 |
| 237 bool NativeMessagingHost::ProcessStopDaemon( | 225 bool NativeMessagingHost::ProcessStopDaemon( |
| 238 const base::DictionaryValue& message, | 226 const base::DictionaryValue& message, |
| 239 scoped_ptr<base::DictionaryValue> response) { | 227 scoped_ptr<base::DictionaryValue> response) { |
| 240 daemon_controller_->Stop(base::Bind( | 228 daemon_controller_->Stop( |
| 241 &NativeMessagingHost::SendAsyncResult, base::Unretained(this), | 229 base::Bind(&NativeMessagingHost::SendAsyncResult, base::Unretained(this), |
| 242 base::Passed(&response))); | 230 base::Passed(&response))); |
| 243 return true; | 231 return true; |
| 244 } | 232 } |
| 245 | 233 |
| 246 bool NativeMessagingHost::ProcessGetDaemonState( | 234 bool NativeMessagingHost::ProcessGetDaemonState( |
| 247 const base::DictionaryValue& message, | 235 const base::DictionaryValue& message, |
| 248 scoped_ptr<base::DictionaryValue> response) { | 236 scoped_ptr<base::DictionaryValue> response) { |
| 249 // TODO(lambroslambrou): Send the state as a string instead of an integer, | 237 // TODO(lambroslambrou): Send the state as a string instead of an integer, |
| 250 // and update the web-app accordingly. | 238 // and update the web-app accordingly. |
| 251 DaemonController::State state = daemon_controller_->GetState(); | 239 DaemonController::State state = daemon_controller_->GetState(); |
| 252 response->SetInteger("state", state); | 240 response->SetInteger("state", state); |
| 253 SendResponse(response.Pass()); | 241 SendResponse(response.Pass()); |
| 254 return true; | 242 return true; |
| 255 } | 243 } |
| 256 | 244 |
| 257 void NativeMessagingHost::SendResponse( | 245 void NativeMessagingHost::SendResponse( |
| 258 scoped_ptr<base::DictionaryValue> response) { | 246 scoped_ptr<base::DictionaryValue> response) { |
| 259 if (!caller_task_runner_->BelongsToCurrentThread()) { | 247 if (!caller_task_runner_->BelongsToCurrentThread()) { |
| 260 caller_task_runner_->PostTask(FROM_HERE, base::Bind( | 248 caller_task_runner_->PostTask( |
| 261 &NativeMessagingHost::SendResponse, weak_ptr_, | 249 FROM_HERE, base::Bind(&NativeMessagingHost::SendResponse, weak_ptr_, |
| 262 base::Passed(&response))); | 250 base::Passed(&response))); |
| 263 return; | 251 return; |
| 264 } | 252 } |
| 265 | 253 |
| 266 if (!native_messaging_writer_.WriteMessage(*response)) | 254 if (!native_messaging_writer_.WriteMessage(*response)) |
| 267 Shutdown(); | 255 Shutdown(); |
| 268 } | 256 } |
| 269 | 257 |
| 270 void NativeMessagingHost::SendConfigResponse( | 258 void NativeMessagingHost::SendConfigResponse( |
| 271 scoped_ptr<base::DictionaryValue> response, | 259 scoped_ptr<base::DictionaryValue> response, |
| 272 scoped_ptr<base::DictionaryValue> config) { | 260 scoped_ptr<base::DictionaryValue> config) { |
| 273 // TODO(lambroslambrou): Fix the web-app to accept the config dictionary | 261 response->Set("config", config.release()); |
| 274 // directly embedded in the response, rather than as serialized JSON. See | |
| 275 // http://crbug.com/232135. | |
| 276 std::string config_json; | |
| 277 base::JSONWriter::Write(config.get(), &config_json); | |
| 278 response->SetString("config", config_json); | |
| 279 SendResponse(response.Pass()); | 262 SendResponse(response.Pass()); |
| 280 } | 263 } |
| 281 | 264 |
| 282 void NativeMessagingHost::SendUsageStatsConsentResponse( | 265 void NativeMessagingHost::SendUsageStatsConsentResponse( |
| 283 scoped_ptr<base::DictionaryValue> response, | 266 scoped_ptr<base::DictionaryValue> response, |
| 284 bool supported, | 267 bool supported, |
| 285 bool allowed, | 268 bool allowed, |
| 286 bool set_by_policy) { | 269 bool set_by_policy) { |
| 287 response->SetBoolean("supported", supported); | 270 response->SetBoolean("supported", supported); |
| 288 response->SetBoolean("allowed", allowed); | 271 response->SetBoolean("allowed", allowed); |
| 289 response->SetBoolean("set_by_policy", set_by_policy); | 272 response->SetBoolean("set_by_policy", set_by_policy); |
| 290 SendResponse(response.Pass()); | 273 SendResponse(response.Pass()); |
| 291 } | 274 } |
| 292 | 275 |
| 293 void NativeMessagingHost::SendAsyncResult( | 276 void NativeMessagingHost::SendAsyncResult( |
| 294 scoped_ptr<base::DictionaryValue> response, | 277 scoped_ptr<base::DictionaryValue> response, |
| 295 DaemonController::AsyncResult result) { | 278 DaemonController::AsyncResult result) { |
| 296 // TODO(lambroslambrou): Send the result as a string instead of an integer, | 279 // TODO(lambroslambrou): Send the result as a string instead of an integer, |
| 297 // and update the web-app accordingly. See http://crbug.com/232135. | 280 // and update the web-app accordingly. See http://crbug.com/232135. |
| 298 response->SetInteger("result", result); | 281 response->SetInteger("result", result); |
| 299 SendResponse(response.Pass()); | 282 SendResponse(response.Pass()); |
| 300 } | 283 } |
| 301 | 284 |
| 302 } // namespace remoting | 285 } // namespace remoting |
| OLD | NEW |