1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "remoting/host/setup/native_messaging_host.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/basictypes.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/callback.h"
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/json/json_string_value_serializer.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/location.h"
144311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include "base/message_loop/message_loop.h"
154311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include "base/run_loop.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/stringize_macros.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/values.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/base/net_util.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/base/rsa_key_pair.h"
204311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include "remoting/host/host_exit_codes.h"
214311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include "remoting/host/pairing_registry_delegate.h"
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "remoting/host/pairing_registry_delegate.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/host/pin_hash.h"
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "remoting/protocol/pairing_registry.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
264311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#if defined(OS_POSIX)
274311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include <unistd.h>
284311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#endif
294311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Features supported in addition to the base protocol.
33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char* kSupportedFeatures[] = {
34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  "pairingRegistry",
35a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)};
36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Helper to extract the "config" part of a message as a DictionaryValue.
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Returns NULL on failure, and logs an error message.
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<base::DictionaryValue> ConfigDictionaryFromMessage(
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& message) {
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result;
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const base::DictionaryValue* config_dict;
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (message.GetDictionary("config", &config_dict)) {
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    result.reset(config_dict->DeepCopy());
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) << "'config' dictionary not found";
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return result.Pass();
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace remoting {
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)NativeMessagingHost::NativeMessagingHost(
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<DaemonController> daemon_controller,
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_refptr<protocol::PairingRegistry> pairing_registry,
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformFile input,
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformFile output,
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Closure& quit_closure)
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : caller_task_runner_(caller_task_runner),
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      quit_closure_(quit_closure),
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      native_messaging_reader_(input),
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      native_messaging_writer_(output),
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      daemon_controller_(daemon_controller.Pass()),
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      pairing_registry_(pairing_registry),
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this) {
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  weak_ptr_ = weak_factory_.GetWeakPtr();
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)NativeMessagingHost::~NativeMessagingHost() {}
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NativeMessagingHost::Start() {
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(caller_task_runner_->BelongsToCurrentThread());
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  native_messaging_reader_.Start(
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&NativeMessagingHost::ProcessMessage, weak_ptr_),
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&NativeMessagingHost::Shutdown, weak_ptr_));
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NativeMessagingHost::Shutdown() {
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(caller_task_runner_->BelongsToCurrentThread());
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!quit_closure_.is_null()) {
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    caller_task_runner_->PostTask(FROM_HERE, quit_closure_);
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    quit_closure_.Reset();
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NativeMessagingHost::ProcessMessage(scoped_ptr<base::Value> message) {
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(caller_task_runner_->BelongsToCurrentThread());
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Don't process any more messages if Shutdown() has been called.
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (quit_closure_.is_null())
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::DictionaryValue* message_dict;
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!message->GetAsDictionary(&message_dict)) {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Expected DictionaryValue";
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Shutdown();
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> response_dict(new base::DictionaryValue());
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If the client supplies an ID, it will expect it in the response. This
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // might be a string or a number, so cope with both.
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::Value* id;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (message_dict->Get("id", &id))
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    response_dict->Set("id", id->DeepCopy());
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string type;
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!message_dict->GetString("type", &type)) {
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "'type' not found";
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Shutdown();
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  response_dict->SetString("type", type + "Response");
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool success = false;
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (type == "hello") {
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    success = ProcessHello(*message_dict, response_dict.Pass());
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else if (type == "clearPairedClients") {
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    success = ProcessClearPairedClients(*message_dict, response_dict.Pass());
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else if (type == "deletePairedClient") {
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    success = ProcessDeletePairedClient(*message_dict, response_dict.Pass());
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (type == "getHostName") {
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    success = ProcessGetHostName(*message_dict, response_dict.Pass());
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (type == "getPinHash") {
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    success = ProcessGetPinHash(*message_dict, response_dict.Pass());
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (type == "generateKeyPair") {
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    success = ProcessGenerateKeyPair(*message_dict, response_dict.Pass());
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (type == "updateDaemonConfig") {
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    success = ProcessUpdateDaemonConfig(*message_dict, response_dict.Pass());
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (type == "getDaemonConfig") {
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    success = ProcessGetDaemonConfig(*message_dict, response_dict.Pass());
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else if (type == "getPairedClients") {
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    success = ProcessGetPairedClients(*message_dict, response_dict.Pass());
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (type == "getUsageStatsConsent") {
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    success = ProcessGetUsageStatsConsent(*message_dict, response_dict.Pass());
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (type == "startDaemon") {
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    success = ProcessStartDaemon(*message_dict, response_dict.Pass());
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (type == "stopDaemon") {
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    success = ProcessStopDaemon(*message_dict, response_dict.Pass());
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (type == "getDaemonState") {
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    success = ProcessGetDaemonState(*message_dict, response_dict.Pass());
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unsupported request type: " << type;
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!success)
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Shutdown();
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool NativeMessagingHost::ProcessHello(
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& message,
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> response) {
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  response->SetString("version", STRINGIZE(VERSION));
160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<base::ListValue> supported_features_list(new base::ListValue());
161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  supported_features_list->AppendStrings(std::vector<std::string>(
162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      kSupportedFeatures, kSupportedFeatures + arraysize(kSupportedFeatures)));
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  response->Set("supportedFeatures", supported_features_list.release());
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendResponse(response.Pass());
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool NativeMessagingHost::ProcessClearPairedClients(
1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const base::DictionaryValue& message,
1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_ptr<base::DictionaryValue> response) {
171bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (pairing_registry_) {
172bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    pairing_registry_->ClearAllPairings(
173bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        base::Bind(&NativeMessagingHost::SendBooleanResult, weak_ptr_,
174bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                   base::Passed(&response)));
175bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  } else {
176bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    SendBooleanResult(response.Pass(), false);
177bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  }
1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool NativeMessagingHost::ProcessDeletePairedClient(
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const base::DictionaryValue& message,
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_ptr<base::DictionaryValue> response) {
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string client_id;
1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!message.GetString(protocol::PairingRegistry::kClientIdKey, &client_id)) {
1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    LOG(ERROR) << "'" << protocol::PairingRegistry::kClientIdKey
1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch               << "' string not found.";
1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
1897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
191bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (pairing_registry_) {
192bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    pairing_registry_->DeletePairing(
193bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        client_id, base::Bind(&NativeMessagingHost::SendBooleanResult,
194bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                              weak_ptr_, base::Passed(&response)));
195bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  } else {
196bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    SendBooleanResult(response.Pass(), false);
197bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  }
1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool NativeMessagingHost::ProcessGetHostName(
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& message,
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> response) {
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  response->SetString("hostname", net::GetHostName());
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendResponse(response.Pass());
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool NativeMessagingHost::ProcessGetPinHash(
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& message,
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> response) {
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string host_id;
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!message.GetString("hostId", &host_id)) {
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "'hostId' not found: " << message;
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string pin;
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!message.GetString("pin", &pin)) {
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "'pin' not found: " << message;
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  response->SetString("hash", remoting::MakeHostPinHash(host_id, pin));
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendResponse(response.Pass());
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool NativeMessagingHost::ProcessGenerateKeyPair(
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& message,
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> response) {
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<RsaKeyPair> key_pair = RsaKeyPair::Generate();
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  response->SetString("privateKey", key_pair->ToString());
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  response->SetString("publicKey", key_pair->GetPublicKey());
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendResponse(response.Pass());
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool NativeMessagingHost::ProcessUpdateDaemonConfig(
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& message,
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> response) {
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> config_dict =
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ConfigDictionaryFromMessage(message);
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!config_dict)
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // base::Unretained() is safe because this object owns |daemon_controller_|
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // which owns the thread that will run the callback.
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  daemon_controller_->UpdateConfig(
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      config_dict.Pass(),
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&NativeMessagingHost::SendAsyncResult, base::Unretained(this),
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Passed(&response)));
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool NativeMessagingHost::ProcessGetDaemonConfig(
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& message,
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> response) {
25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  daemon_controller_->GetConfig(
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&NativeMessagingHost::SendConfigResponse,
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 base::Unretained(this), base::Passed(&response)));
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool NativeMessagingHost::ProcessGetPairedClients(
2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const base::DictionaryValue& message,
2657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_ptr<base::DictionaryValue> response) {
266bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (pairing_registry_) {
267bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    pairing_registry_->GetAllPairings(
268bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        base::Bind(&NativeMessagingHost::SendPairedClientsResponse, weak_ptr_,
269bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                   base::Passed(&response)));
270bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  } else {
271bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    scoped_ptr<base::ListValue> no_paired_clients(new base::ListValue);
272bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    SendPairedClientsResponse(response.Pass(), no_paired_clients.Pass());
273bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  }
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
2757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool NativeMessagingHost::ProcessGetUsageStatsConsent(
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& message,
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> response) {
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  daemon_controller_->GetUsageStatsConsent(
28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&NativeMessagingHost::SendUsageStatsConsentResponse,
28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 base::Unretained(this), base::Passed(&response)));
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool NativeMessagingHost::ProcessStartDaemon(
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& message,
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> response) {
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool consent;
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!message.GetBoolean("consent", &consent)) {
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "'consent' not found.";
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> config_dict =
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ConfigDictionaryFromMessage(message);
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!config_dict)
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  daemon_controller_->SetConfigAndStart(
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      config_dict.Pass(), consent,
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&NativeMessagingHost::SendAsyncResult, base::Unretained(this),
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Passed(&response)));
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool NativeMessagingHost::ProcessStopDaemon(
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& message,
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> response) {
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  daemon_controller_->Stop(
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&NativeMessagingHost::SendAsyncResult, base::Unretained(this),
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 base::Passed(&response)));
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool NativeMessagingHost::ProcessGetDaemonState(
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& message,
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> response) {
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DaemonController::State state = daemon_controller_->GetState();
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  switch (state) {
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case DaemonController::STATE_NOT_IMPLEMENTED:
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      response->SetString("state", "NOT_IMPLEMENTED");
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case DaemonController::STATE_NOT_INSTALLED:
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      response->SetString("state", "NOT_INSTALLED");
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case DaemonController::STATE_INSTALLING:
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      response->SetString("state", "INSTALLING");
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case DaemonController::STATE_STOPPED:
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      response->SetString("state", "STOPPED");
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case DaemonController::STATE_STARTING:
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      response->SetString("state", "STARTING");
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case DaemonController::STATE_STARTED:
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      response->SetString("state", "STARTED");
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case DaemonController::STATE_STOPPING:
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      response->SetString("state", "STOPPING");
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case DaemonController::STATE_UNKNOWN:
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      response->SetString("state", "UNKNOWN");
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendResponse(response.Pass());
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NativeMessagingHost::SendResponse(
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> response) {
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!caller_task_runner_->BelongsToCurrentThread()) {
35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    caller_task_runner_->PostTask(
35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        FROM_HERE, base::Bind(&NativeMessagingHost::SendResponse, weak_ptr_,
35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              base::Passed(&response)));
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!native_messaging_writer_.WriteMessage(*response))
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Shutdown();
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NativeMessagingHost::SendConfigResponse(
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> response,
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> config) {
366ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (config) {
367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    response->Set("config", config.release());
368ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  } else {
369ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    response->Set("config", Value::CreateNullValue());
370ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendResponse(response.Pass());
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid NativeMessagingHost::SendPairedClientsResponse(
3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_ptr<base::DictionaryValue> response,
3767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_ptr<base::ListValue> pairings) {
3777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  response->Set("pairedClients", pairings.release());
3787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SendResponse(response.Pass());
3797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
3807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NativeMessagingHost::SendUsageStatsConsentResponse(
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> response,
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool supported,
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool allowed,
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool set_by_policy) {
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  response->SetBoolean("supported", supported);
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  response->SetBoolean("allowed", allowed);
388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  response->SetBoolean("setByPolicy", set_by_policy);
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendResponse(response.Pass());
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NativeMessagingHost::SendAsyncResult(
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> response,
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DaemonController::AsyncResult result) {
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  switch (result) {
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case DaemonController::RESULT_OK:
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      response->SetString("result", "OK");
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case DaemonController::RESULT_FAILED:
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      response->SetString("result", "FAILED");
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case DaemonController::RESULT_CANCELLED:
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      response->SetString("result", "CANCELLED");
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case DaemonController::RESULT_FAILED_DIRECTORY:
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      response->SetString("result", "FAILED_DIRECTORY");
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendResponse(response.Pass());
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid NativeMessagingHost::SendBooleanResult(
4137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_ptr<base::DictionaryValue> response, bool result) {
4149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  response->SetBoolean("result", result);
4159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  SendResponse(response.Pass());
4167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
4177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4184311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdochint NativeMessagingHostMain() {
4194311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#if defined(OS_WIN)
4204311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  base::PlatformFile read_file = GetStdHandle(STD_INPUT_HANDLE);
4214311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  base::PlatformFile write_file = GetStdHandle(STD_OUTPUT_HANDLE);
4224311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#elif defined(OS_POSIX)
4234311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  base::PlatformFile read_file = STDIN_FILENO;
4244311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  base::PlatformFile write_file = STDOUT_FILENO;
4254311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#else
4264311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#error Not implemented.
4274311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#endif
4284311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch
4294311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
4304311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  base::RunLoop run_loop;
4314311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  scoped_refptr<protocol::PairingRegistry> pairing_registry =
4324311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      CreatePairingRegistry(message_loop.message_loop_proxy());
4334311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  remoting::NativeMessagingHost host(remoting::DaemonController::Create(),
4344311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch                                     pairing_registry,
4354311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch                                     read_file, write_file,
4364311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch                                     message_loop.message_loop_proxy(),
4374311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch                                     run_loop.QuitClosure());
4384311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  host.Start();
4394311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  run_loop.Run();
4404311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  return kSuccessExitCode;
4414311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch}
4424311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace remoting
444