Index: remoting/host/setup/native_messaging_host.cc |
diff --git a/remoting/host/setup/native_messaging_host.cc b/remoting/host/setup/native_messaging_host.cc |
deleted file mode 100644 |
index 38ecdb1e5987d3c37c093515fc7bcabf68db287a..0000000000000000000000000000000000000000 |
--- a/remoting/host/setup/native_messaging_host.cc |
+++ /dev/null |
@@ -1,514 +0,0 @@ |
-// Copyright 2013 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "remoting/host/setup/native_messaging_host.h" |
- |
-#include <string> |
- |
-#include "base/basictypes.h" |
-#include "base/bind.h" |
-#include "base/callback.h" |
-#include "base/command_line.h" |
-#include "base/logging.h" |
-#include "base/message_loop/message_loop.h" |
-#include "base/run_loop.h" |
-#include "base/strings/string_number_conversions.h" |
-#include "base/strings/stringize_macros.h" |
-#include "base/threading/thread.h" |
-#include "base/values.h" |
-#include "google_apis/gaia/gaia_oauth_client.h" |
-#include "google_apis/google_api_keys.h" |
-#include "net/base/net_util.h" |
-#include "net/url_request/url_fetcher.h" |
-#include "remoting/base/rsa_key_pair.h" |
-#include "remoting/base/url_request_context.h" |
-#include "remoting/host/host_exit_codes.h" |
-#include "remoting/host/pairing_registry_delegate.h" |
-#include "remoting/host/pin_hash.h" |
-#include "remoting/host/setup/oauth_client.h" |
-#include "remoting/protocol/pairing_registry.h" |
- |
-namespace { |
- |
-const char kParentWindowSwitchName[] = "parent-window"; |
- |
-// redirect_uri to use when authenticating service accounts (service account |
-// codes are obtained "out-of-band", i.e., not through an OAuth redirect). |
-const char* kServiceAccountRedirectUri = "oob"; |
- |
-// Features supported in addition to the base protocol. |
-const char* kSupportedFeatures[] = { |
- "pairingRegistry", |
- "oauthClient" |
-}; |
- |
-// Helper to extract the "config" part of a message as a DictionaryValue. |
-// Returns NULL on failure, and logs an error message. |
-scoped_ptr<base::DictionaryValue> ConfigDictionaryFromMessage( |
- const base::DictionaryValue& message) { |
- scoped_ptr<base::DictionaryValue> result; |
- const base::DictionaryValue* config_dict; |
- if (message.GetDictionary("config", &config_dict)) { |
- result.reset(config_dict->DeepCopy()); |
- } else { |
- LOG(ERROR) << "'config' dictionary not found"; |
- } |
- return result.Pass(); |
-} |
- |
-} // namespace |
- |
-namespace remoting { |
- |
-NativeMessagingHost::NativeMessagingHost( |
- scoped_refptr<DaemonController> daemon_controller, |
- scoped_refptr<protocol::PairingRegistry> pairing_registry, |
- scoped_ptr<OAuthClient> oauth_client) |
- : daemon_controller_(daemon_controller), |
- pairing_registry_(pairing_registry), |
- oauth_client_(oauth_client.Pass()), |
- weak_factory_(this) { |
- weak_ptr_ = weak_factory_.GetWeakPtr(); |
-} |
- |
-NativeMessagingHost::~NativeMessagingHost() { |
-} |
- |
-void NativeMessagingHost::ProcessMessage( |
- scoped_ptr<base::DictionaryValue> message, |
- const SendResponseCallback& done) { |
- scoped_ptr<base::DictionaryValue> response(new base::DictionaryValue()); |
- |
- // If the client supplies an ID, it will expect it in the response. This |
- // might be a string or a number, so cope with both. |
- const base::Value* id; |
- if (message->Get("id", &id)) |
- response->Set("id", id->DeepCopy()); |
- |
- std::string type; |
- if (!message->GetString("type", &type)) { |
- LOG(ERROR) << "'type' not found"; |
- done.Run(scoped_ptr<base::DictionaryValue>()); |
- return; |
- } |
- |
- response->SetString("type", type + "Response"); |
- |
- bool success = false; |
- if (type == "hello") { |
- success = ProcessHello(*message, response.Pass(), done); |
- } else if (type == "clearPairedClients") { |
- success = ProcessClearPairedClients(*message, response.Pass(), done); |
- } else if (type == "deletePairedClient") { |
- success = ProcessDeletePairedClient(*message, response.Pass(), done); |
- } else if (type == "getHostName") { |
- success = ProcessGetHostName(*message, response.Pass(), done); |
- } else if (type == "getPinHash") { |
- success = ProcessGetPinHash(*message, response.Pass(), done); |
- } else if (type == "generateKeyPair") { |
- success = ProcessGenerateKeyPair(*message, response.Pass(), done); |
- } else if (type == "updateDaemonConfig") { |
- success = ProcessUpdateDaemonConfig(*message, response.Pass(), done); |
- } else if (type == "getDaemonConfig") { |
- success = ProcessGetDaemonConfig(*message, response.Pass(), done); |
- } else if (type == "getPairedClients") { |
- success = ProcessGetPairedClients(*message, response.Pass(), done); |
- } else if (type == "getUsageStatsConsent") { |
- success = ProcessGetUsageStatsConsent(*message, response.Pass(), done); |
- } else if (type == "startDaemon") { |
- success = ProcessStartDaemon(*message, response.Pass(), done); |
- } else if (type == "stopDaemon") { |
- success = ProcessStopDaemon(*message, response.Pass(), done); |
- } else if (type == "getDaemonState") { |
- success = ProcessGetDaemonState(*message, response.Pass(), done); |
- } else if (type == "getHostClientId") { |
- success = ProcessGetHostClientId(*message, response.Pass(), done); |
- } else if (type == "getCredentialsFromAuthCode") { |
- success = ProcessGetCredentialsFromAuthCode(*message, response.Pass(), |
- done); |
- } else { |
- LOG(ERROR) << "Unsupported request type: " << type; |
- } |
- |
- if (!success) |
- done.Run(scoped_ptr<base::DictionaryValue>()); |
-} |
- |
-bool NativeMessagingHost::ProcessHello( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- response->SetString("version", STRINGIZE(VERSION)); |
- scoped_ptr<base::ListValue> supported_features_list(new base::ListValue()); |
- supported_features_list->AppendStrings(std::vector<std::string>( |
- kSupportedFeatures, kSupportedFeatures + arraysize(kSupportedFeatures))); |
- response->Set("supportedFeatures", supported_features_list.release()); |
- done.Run(response.Pass()); |
- return true; |
-} |
- |
-bool NativeMessagingHost::ProcessClearPairedClients( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- if (pairing_registry_) { |
- pairing_registry_->ClearAllPairings( |
- base::Bind(&NativeMessagingHost::SendBooleanResult, weak_ptr_, |
- done, base::Passed(&response))); |
- } else { |
- SendBooleanResult(done, response.Pass(), false); |
- } |
- return true; |
-} |
- |
-bool NativeMessagingHost::ProcessDeletePairedClient( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- std::string client_id; |
- if (!message.GetString(protocol::PairingRegistry::kClientIdKey, &client_id)) { |
- LOG(ERROR) << "'" << protocol::PairingRegistry::kClientIdKey |
- << "' string not found."; |
- return false; |
- } |
- |
- if (pairing_registry_) { |
- pairing_registry_->DeletePairing( |
- client_id, base::Bind(&NativeMessagingHost::SendBooleanResult, |
- weak_ptr_, done, base::Passed(&response))); |
- } else { |
- SendBooleanResult(done, response.Pass(), false); |
- } |
- return true; |
-} |
- |
-bool NativeMessagingHost::ProcessGetHostName( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- response->SetString("hostname", net::GetHostName()); |
- done.Run(response.Pass()); |
- return true; |
-} |
- |
-bool NativeMessagingHost::ProcessGetPinHash( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- std::string host_id; |
- if (!message.GetString("hostId", &host_id)) { |
- LOG(ERROR) << "'hostId' not found: " << message; |
- return false; |
- } |
- std::string pin; |
- if (!message.GetString("pin", &pin)) { |
- LOG(ERROR) << "'pin' not found: " << message; |
- return false; |
- } |
- response->SetString("hash", MakeHostPinHash(host_id, pin)); |
- done.Run(response.Pass()); |
- return true; |
-} |
- |
-bool NativeMessagingHost::ProcessGenerateKeyPair( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- scoped_refptr<RsaKeyPair> key_pair = RsaKeyPair::Generate(); |
- response->SetString("privateKey", key_pair->ToString()); |
- response->SetString("publicKey", key_pair->GetPublicKey()); |
- done.Run(response.Pass()); |
- return true; |
-} |
- |
-bool NativeMessagingHost::ProcessUpdateDaemonConfig( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- scoped_ptr<base::DictionaryValue> config_dict = |
- ConfigDictionaryFromMessage(message); |
- if (!config_dict) |
- return false; |
- |
- daemon_controller_->UpdateConfig( |
- config_dict.Pass(), |
- base::Bind(&NativeMessagingHost::SendAsyncResult, weak_ptr_, |
- done, base::Passed(&response))); |
- return true; |
-} |
- |
-bool NativeMessagingHost::ProcessGetDaemonConfig( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- daemon_controller_->GetConfig( |
- base::Bind(&NativeMessagingHost::SendConfigResponse, weak_ptr_, |
- done, base::Passed(&response))); |
- return true; |
-} |
- |
-bool NativeMessagingHost::ProcessGetPairedClients( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- if (pairing_registry_) { |
- pairing_registry_->GetAllPairings( |
- base::Bind(&NativeMessagingHost::SendPairedClientsResponse, weak_ptr_, |
- done, base::Passed(&response))); |
- } else { |
- scoped_ptr<base::ListValue> no_paired_clients(new base::ListValue); |
- SendPairedClientsResponse(done, response.Pass(), no_paired_clients.Pass()); |
- } |
- return true; |
-} |
- |
-bool NativeMessagingHost::ProcessGetUsageStatsConsent( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- daemon_controller_->GetUsageStatsConsent( |
- base::Bind(&NativeMessagingHost::SendUsageStatsConsentResponse, |
- weak_ptr_, done, base::Passed(&response))); |
- return true; |
-} |
- |
-bool NativeMessagingHost::ProcessStartDaemon( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- bool consent; |
- if (!message.GetBoolean("consent", &consent)) { |
- LOG(ERROR) << "'consent' not found."; |
- return false; |
- } |
- |
- scoped_ptr<base::DictionaryValue> config_dict = |
- ConfigDictionaryFromMessage(message); |
- if (!config_dict) |
- return false; |
- |
- daemon_controller_->SetConfigAndStart( |
- config_dict.Pass(), consent, |
- base::Bind(&NativeMessagingHost::SendAsyncResult, weak_ptr_, |
- done, base::Passed(&response))); |
- return true; |
-} |
- |
-bool NativeMessagingHost::ProcessStopDaemon( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- daemon_controller_->Stop( |
- base::Bind(&NativeMessagingHost::SendAsyncResult, weak_ptr_, |
- done, base::Passed(&response))); |
- return true; |
-} |
- |
-bool NativeMessagingHost::ProcessGetDaemonState( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- DaemonController::State state = daemon_controller_->GetState(); |
- switch (state) { |
- case DaemonController::STATE_NOT_IMPLEMENTED: |
- response->SetString("state", "NOT_IMPLEMENTED"); |
- break; |
- case DaemonController::STATE_NOT_INSTALLED: |
- response->SetString("state", "NOT_INSTALLED"); |
- break; |
- case DaemonController::STATE_INSTALLING: |
- response->SetString("state", "INSTALLING"); |
- break; |
- case DaemonController::STATE_STOPPED: |
- response->SetString("state", "STOPPED"); |
- break; |
- case DaemonController::STATE_STARTING: |
- response->SetString("state", "STARTING"); |
- break; |
- case DaemonController::STATE_STARTED: |
- response->SetString("state", "STARTED"); |
- break; |
- case DaemonController::STATE_STOPPING: |
- response->SetString("state", "STOPPING"); |
- break; |
- case DaemonController::STATE_UNKNOWN: |
- response->SetString("state", "UNKNOWN"); |
- break; |
- } |
- done.Run(response.Pass()); |
- return true; |
-} |
- |
-bool NativeMessagingHost::ProcessGetHostClientId( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- response->SetString("clientId", google_apis::GetOAuth2ClientID( |
- google_apis::CLIENT_REMOTING_HOST)); |
- done.Run(response.Pass()); |
- return true; |
-} |
- |
-bool NativeMessagingHost::ProcessGetCredentialsFromAuthCode( |
- const base::DictionaryValue& message, |
- scoped_ptr<base::DictionaryValue> response, |
- const SendResponseCallback& done) { |
- std::string auth_code; |
- if (!message.GetString("authorizationCode", &auth_code)) { |
- LOG(ERROR) << "'authorizationCode' string not found."; |
- return false; |
- } |
- |
- gaia::OAuthClientInfo oauth_client_info = { |
- google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING_HOST), |
- google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_REMOTING_HOST), |
- kServiceAccountRedirectUri |
- }; |
- |
- oauth_client_->GetCredentialsFromAuthCode( |
- oauth_client_info, auth_code, base::Bind( |
- &NativeMessagingHost::SendCredentialsResponse, weak_ptr_, |
- done, base::Passed(&response))); |
- |
- return true; |
-} |
- |
-void NativeMessagingHost::SendConfigResponse( |
- const SendResponseCallback& done, |
- scoped_ptr<base::DictionaryValue> response, |
- scoped_ptr<base::DictionaryValue> config) { |
- if (config) { |
- response->Set("config", config.release()); |
- } else { |
- response->Set("config", Value::CreateNullValue()); |
- } |
- done.Run(response.Pass()); |
-} |
- |
-void NativeMessagingHost::SendPairedClientsResponse( |
- const SendResponseCallback& done, |
- scoped_ptr<base::DictionaryValue> response, |
- scoped_ptr<base::ListValue> pairings) { |
- response->Set("pairedClients", pairings.release()); |
- done.Run(response.Pass()); |
-} |
- |
-void NativeMessagingHost::SendUsageStatsConsentResponse( |
- const SendResponseCallback& done, |
- scoped_ptr<base::DictionaryValue> response, |
- const DaemonController::UsageStatsConsent& consent) { |
- response->SetBoolean("supported", consent.supported); |
- response->SetBoolean("allowed", consent.allowed); |
- response->SetBoolean("setByPolicy", consent.set_by_policy); |
- done.Run(response.Pass()); |
-} |
- |
-void NativeMessagingHost::SendAsyncResult( |
- const SendResponseCallback& done, |
- scoped_ptr<base::DictionaryValue> response, |
- DaemonController::AsyncResult result) { |
- switch (result) { |
- case DaemonController::RESULT_OK: |
- response->SetString("result", "OK"); |
- break; |
- case DaemonController::RESULT_FAILED: |
- response->SetString("result", "FAILED"); |
- break; |
- case DaemonController::RESULT_CANCELLED: |
- response->SetString("result", "CANCELLED"); |
- break; |
- case DaemonController::RESULT_FAILED_DIRECTORY: |
- response->SetString("result", "FAILED_DIRECTORY"); |
- break; |
- } |
- done.Run(response.Pass()); |
-} |
- |
-void NativeMessagingHost::SendBooleanResult( |
- const SendResponseCallback& done, |
- scoped_ptr<base::DictionaryValue> response, bool result) { |
- response->SetBoolean("result", result); |
- done.Run(response.Pass()); |
-} |
- |
-void NativeMessagingHost::SendCredentialsResponse( |
- const SendResponseCallback& done, |
- scoped_ptr<base::DictionaryValue> response, |
- const std::string& user_email, |
- const std::string& refresh_token) { |
- response->SetString("userEmail", user_email); |
- response->SetString("refreshToken", refresh_token); |
- done.Run(response.Pass()); |
-} |
- |
-int NativeMessagingHostMain() { |
-#if defined(OS_WIN) |
- // GetStdHandle() returns pseudo-handles for stdin and stdout even if |
- // the hosting executable specifies "Windows" subsystem. However the returned |
- // handles are invalid in that case unless standard input and output are |
- // redirected to a pipe or file. |
- base::PlatformFile read_file = GetStdHandle(STD_INPUT_HANDLE); |
- base::PlatformFile write_file = GetStdHandle(STD_OUTPUT_HANDLE); |
-#elif defined(OS_POSIX) |
- base::PlatformFile read_file = STDIN_FILENO; |
- base::PlatformFile write_file = STDOUT_FILENO; |
-#else |
-#error Not implemented. |
-#endif |
- |
- // Mac OS X requires that the main thread be a UI message loop in order to |
- // receive distributed notifications from the System Preferences pane. An |
- // IO thread is needed for the pairing registry and URL context getter. |
- base::Thread io_thread("io_thread"); |
- io_thread.StartWithOptions( |
- base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); |
- |
- base::MessageLoopForUI message_loop; |
- base::RunLoop run_loop; |
- |
- scoped_refptr<DaemonController> daemon_controller = |
- DaemonController::Create(); |
- |
- // Pass handle of the native view to the controller so that the UAC prompts |
- // are focused properly. |
- const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
- if (command_line->HasSwitch(kParentWindowSwitchName)) { |
- std::string native_view = |
- command_line->GetSwitchValueASCII(kParentWindowSwitchName); |
- int64 native_view_handle = 0; |
- if (base::StringToInt64(native_view, &native_view_handle)) { |
- daemon_controller->SetWindow(reinterpret_cast<void*>(native_view_handle)); |
- } else { |
- LOG(WARNING) << "Invalid parameter value --" << kParentWindowSwitchName |
- << "=" << native_view; |
- } |
- } |
- |
- // OAuth client (for credential requests). |
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter( |
- new URLRequestContextGetter(io_thread.message_loop_proxy())); |
- scoped_ptr<OAuthClient> oauth_client( |
- new OAuthClient(url_request_context_getter)); |
- |
- net::URLFetcher::SetIgnoreCertificateRequests(true); |
- |
- // Create the pairing registry and native messaging host. |
- scoped_refptr<protocol::PairingRegistry> pairing_registry = |
- CreatePairingRegistry(io_thread.message_loop_proxy()); |
- scoped_ptr<NativeMessagingChannel::Delegate> host( |
- new NativeMessagingHost(daemon_controller, |
- pairing_registry, |
- oauth_client.Pass())); |
- |
- // Set up the native messaging channel. |
- scoped_ptr<NativeMessagingChannel> channel( |
- new NativeMessagingChannel(host.Pass(), read_file, write_file)); |
- channel->Start(run_loop.QuitClosure()); |
- |
- // Run the loop until channel is alive. |
- run_loop.Run(); |
- return kSuccessExitCode; |
-} |
- |
-} // namespace remoting |