// 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/it2me/it2me_native_messaging_host.h"

#include <memory>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringize_macros.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/policy/policy_constants.h"
#include "net/base/url_util.h"
#include "net/socket/client_socket_factory.h"
#include "net/url_request/url_request_context_getter.h"
#include "remoting/base/auto_thread_task_runner.h"
#include "remoting/base/name_value_map.h"
#include "remoting/base/service_urls.h"
#include "remoting/host/chromoting_host_context.h"
#include "remoting/host/host_exit_codes.h"
#include "remoting/host/it2me/it2me_confirmation_dialog.h"
#include "remoting/host/policy_watcher.h"
#include "remoting/signaling/delegating_signal_strategy.h"

#if defined(OS_WIN)
#include "base/command_line.h"
#include "base/files/file_path.h"

#include "remoting/host/win/elevated_native_messaging_host.h"
#endif  // defined(OS_WIN)

namespace remoting {

namespace {

const NameMapElement<It2MeHostState> kIt2MeHostStates[] = {
    {kDisconnected, "DISCONNECTED"},
    {kStarting, "STARTING"},
    {kRequestedAccessCode, "REQUESTED_ACCESS_CODE"},
    {kReceivedAccessCode, "RECEIVED_ACCESS_CODE"},
    {kConnecting, "CONNECTING"},
    {kConnected, "CONNECTED"},
    {kError, "ERROR"},
    {kInvalidDomainError, "INVALID_DOMAIN_ERROR"},
};

#if defined(OS_WIN)
const base::FilePath::CharType kBaseHostBinaryName[] =
    FILE_PATH_LITERAL("remote_assistance_host.exe");
const base::FilePath::CharType kElevatedHostBinaryName[] =
    FILE_PATH_LITERAL("remote_assistance_host_uiaccess.exe");
#endif  // defined(OS_WIN)

// Helper functions to run |callback| asynchronously on the correct thread
// using |task_runner|.
void PolicyUpdateCallback(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
    remoting::PolicyWatcher::PolicyUpdatedCallback callback,
    std::unique_ptr<base::DictionaryValue> policies) {
  DCHECK(callback);
  task_runner->PostTask(FROM_HERE,
                        base::Bind(callback, base::Passed(&policies)));
}

void PolicyErrorCallback(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
    remoting::PolicyWatcher::PolicyErrorCallback callback) {
  DCHECK(callback);
  task_runner->PostTask(FROM_HERE, callback);
}

}  // namespace

It2MeNativeMessagingHost::It2MeNativeMessagingHost(
    bool needs_elevation,
    std::unique_ptr<PolicyWatcher> policy_watcher,
    std::unique_ptr<ChromotingHostContext> context,
    std::unique_ptr<It2MeHostFactory> factory)
    : needs_elevation_(needs_elevation),
      host_context_(std::move(context)),
      factory_(std::move(factory)),
      policy_watcher_(std::move(policy_watcher)),
      weak_factory_(this) {
  weak_ptr_ = weak_factory_.GetWeakPtr();

  // The policy watcher runs on the |file_task_runner| but we want to run the
  // callbacks on |task_runner| so we use a shim to post them to it.
  PolicyWatcher::PolicyUpdatedCallback update_callback =
      base::Bind(&It2MeNativeMessagingHost::OnPolicyUpdate, weak_ptr_);
  PolicyWatcher::PolicyErrorCallback error_callback =
      base::Bind(&It2MeNativeMessagingHost::OnPolicyError, weak_ptr_);
  policy_watcher_->StartWatching(
      base::Bind(&PolicyUpdateCallback, task_runner(), update_callback),
      base::Bind(&PolicyErrorCallback, task_runner(), error_callback));
}

It2MeNativeMessagingHost::~It2MeNativeMessagingHost() {
  DCHECK(task_runner()->BelongsToCurrentThread());

  if (it2me_host_.get()) {
    it2me_host_->Disconnect();
    it2me_host_ = nullptr;
  }
}

void It2MeNativeMessagingHost::OnMessage(const std::string& message) {
  DCHECK(task_runner()->BelongsToCurrentThread());

  std::unique_ptr<base::DictionaryValue> response(new base::DictionaryValue());
  std::unique_ptr<base::Value> message_value = base::JSONReader::Read(message);
  if (!message_value->IsType(base::Value::Type::DICTIONARY)) {
    LOG(ERROR) << "Received a message that's not a dictionary.";
    client_->CloseChannel(std::string());
    return;
  }

  std::unique_ptr<base::DictionaryValue> message_dict(
      static_cast<base::DictionaryValue*>(message_value.release()));

  // 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_dict->Get("id", &id))
    response->Set("id", base::MakeUnique<base::Value>(*id));

  std::string type;
  if (!message_dict->GetString("type", &type)) {
    SendErrorAndExit(std::move(response), "'type' not found in request.");
    return;
  }

  response->SetString("type", type + "Response");

  if (type == "hello") {
    ProcessHello(std::move(message_dict), std::move(response));
  } else if (type == "connect") {
    ProcessConnect(std::move(message_dict), std::move(response));
  } else if (type == "disconnect") {
    ProcessDisconnect(std::move(message_dict), std::move(response));
  } else if (type == "incomingIq") {
    ProcessIncomingIq(std::move(message_dict), std::move(response));
  } else {
    SendErrorAndExit(std::move(response), "Unsupported request type: " + type);
  }
}

void It2MeNativeMessagingHost::Start(Client* client) {
  DCHECK(task_runner()->BelongsToCurrentThread());
  client_ = client;
#if !defined(OS_CHROMEOS)
  log_message_handler_.reset(
      new LogMessageHandler(
          base::Bind(&It2MeNativeMessagingHost::SendMessageToClient,
                     base::Unretained(this))));
#endif  // !defined(OS_CHROMEOS)
}

void It2MeNativeMessagingHost::SendMessageToClient(
    std::unique_ptr<base::Value> message) const {
  DCHECK(task_runner()->BelongsToCurrentThread());
  std::string message_json;
  base::JSONWriter::Write(*message, &message_json);
  client_->PostMessageFromNativeHost(message_json);
}

void It2MeNativeMessagingHost::ProcessHello(
    std::unique_ptr<base::DictionaryValue> message,
    std::unique_ptr<base::DictionaryValue> response) const {
  DCHECK(task_runner()->BelongsToCurrentThread());

  response->SetString("version", STRINGIZE(VERSION));

  // This list will be populated when new features are added.
  response->Set("supportedFeatures", base::MakeUnique<base::ListValue>());

  SendMessageToClient(std::move(response));
}

void It2MeNativeMessagingHost::ProcessConnect(
    std::unique_ptr<base::DictionaryValue> message,
    std::unique_ptr<base::DictionaryValue> response) {
  DCHECK(task_runner()->BelongsToCurrentThread());

  if (!policy_received_) {
    DCHECK(!pending_connect_);
    pending_connect_ =
        base::Bind(&It2MeNativeMessagingHost::ProcessConnect, weak_ptr_,
                   base::Passed(&message), base::Passed(&response));
    return;
  }

  if (needs_elevation_) {
    // Attempt to pass the current message to the elevated process.  This method
    // will spin up the elevated process if it is not already running.  On
    // success, the elevated process will process the message and respond.
    // If the process cannot be started or message passing fails, then return an
    // error to the message sender.
    if (!DelegateToElevatedHost(std::move(message))) {
      SendErrorAndExit(std::move(response),
                       "Failed to send message to elevated host.");
    }
    return;
  }

  if (it2me_host_.get()) {
    SendErrorAndExit(std::move(response),
                     "Connect can be called only when disconnected.");
    return;
  }

  std::string username;
  if (!message->GetString("userName", &username)) {
    SendErrorAndExit(std::move(response), "'userName' not found in request.");
    return;
  }

  bool use_signaling_proxy = false;
  message->GetBoolean("useSignalingProxy", &use_signaling_proxy);

  const ServiceUrls* service_urls = ServiceUrls::GetInstance();
  std::unique_ptr<SignalStrategy> signal_strategy;

  if (!use_signaling_proxy) {
    XmppSignalStrategy::XmppServerConfig xmpp_config;
    xmpp_config.username = username;

    const bool xmpp_server_valid =
        net::ParseHostAndPort(service_urls->xmpp_server_address(),
                              &xmpp_config.host, &xmpp_config.port);
    DCHECK(xmpp_server_valid);
    xmpp_config.use_tls = service_urls->xmpp_server_use_tls();

    std::string auth_service_with_token;
    if (!message->GetString("authServiceWithToken", &auth_service_with_token)) {
      SendErrorAndExit(std::move(response),
                       "'authServiceWithToken' not found in request.");
      return;
    }

    // For backward compatibility the webapp still passes OAuth service as part
    // of the authServiceWithToken field. But auth service part is always
    // expected to be set to oauth2.
    const char kOAuth2ServicePrefix[] = "oauth2:";
    if (!base::StartsWith(auth_service_with_token, kOAuth2ServicePrefix,
                          base::CompareCase::SENSITIVE)) {
      SendErrorAndExit(std::move(response), "Invalid 'authServiceWithToken': " +
                                                auth_service_with_token);
      return;
    }

    xmpp_config.auth_token =
        auth_service_with_token.substr(strlen(kOAuth2ServicePrefix));

#if !defined(NDEBUG)
    std::string address;
    if (!message->GetString("xmppServerAddress", &address)) {
      SendErrorAndExit(std::move(response),
                       "'xmppServerAddress' not found in request.");
      return;
    }

    if (!net::ParseHostAndPort(address, &xmpp_config.host, &xmpp_config.port)) {
      SendErrorAndExit(std::move(response),
                       "Invalid 'xmppServerAddress': " + address);
      return;
    }

    if (!message->GetBoolean("xmppServerUseTls", &xmpp_config.use_tls)) {
      SendErrorAndExit(std::move(response),
                       "'xmppServerUseTls' not found in request.");
      return;
    }
#endif  // !defined(NDEBUG)

    signal_strategy.reset(new XmppSignalStrategy(
        net::ClientSocketFactory::GetDefaultFactory(),
        host_context_->url_request_context_getter(), xmpp_config));
  } else {
    std::string local_jid;

    if (!message->GetString("localJid", &local_jid)) {
      SendErrorAndExit(std::move(response), "'localJid' not found in request.");
      return;
    }

    auto delegating_signal_strategy =
        base::MakeUnique<DelegatingSignalStrategy>(
            SignalingAddress(local_jid), host_context_->network_task_runner(),
            base::Bind(&It2MeNativeMessagingHost::SendOutgoingIq,
                       weak_factory_.GetWeakPtr()));
    incoming_message_callback_ =
        delegating_signal_strategy->GetIncomingMessageCallback();
    signal_strategy = std::move(delegating_signal_strategy);
  }

  std::string directory_bot_jid = service_urls->directory_bot_jid();

#if !defined(NDEBUG)
  if (!message->GetString("directoryBotJid", &directory_bot_jid)) {
    SendErrorAndExit(std::move(response),
                     "'directoryBotJid' not found in request.");
    return;
  }
#endif  // !defined(NDEBUG)

  std::unique_ptr<base::DictionaryValue> policies =
      policy_watcher_->GetCurrentPolicies();
  if (policies->size() == 0) {
    // At this point policies have been read, so if there are none set then
    // it indicates an error. Since this can be fixed by end users it has a
    // dedicated message type rather than the generic "error" so that the
    // right error message can be displayed.
    SendPolicyErrorAndExit();
    return;
  }

  // Create the It2Me host and start connecting.
  it2me_host_ = factory_->CreateIt2MeHost();
  it2me_host_->Connect(host_context_->Copy(), std::move(policies),
                       base::MakeUnique<It2MeConfirmationDialogFactory>(),
                       weak_ptr_, std::move(signal_strategy), username,
                       directory_bot_jid);

  SendMessageToClient(std::move(response));
}

void It2MeNativeMessagingHost::ProcessDisconnect(
    std::unique_ptr<base::DictionaryValue> message,
    std::unique_ptr<base::DictionaryValue> response) {
  DCHECK(task_runner()->BelongsToCurrentThread());
  DCHECK(policy_received_);

  if (needs_elevation_) {
    // Attempt to pass the current message to the elevated process.  This method
    // will spin up the elevated process if it is not already running.  On
    // success, the elevated process will process the message and respond.
    // If the process cannot be started or message passing fails, then return an
    // error to the message sender.
    if (!DelegateToElevatedHost(std::move(message))) {
      SendErrorAndExit(std::move(response),
                       "Failed to send message to elevated host.");
    }
    return;
  }

  if (it2me_host_.get()) {
    it2me_host_->Disconnect();
    it2me_host_ = nullptr;
  }
  SendMessageToClient(std::move(response));
}

void It2MeNativeMessagingHost::ProcessIncomingIq(
    std::unique_ptr<base::DictionaryValue> message,
    std::unique_ptr<base::DictionaryValue> response) {
  std::string iq;
  if (!message->GetString("iq", &iq)) {
    LOG(ERROR) << "Invalid incomingIq() data.";
    return;
  }

  incoming_message_callback_.Run(iq);
  SendMessageToClient(std::move(response));
};

void It2MeNativeMessagingHost::SendOutgoingIq(const std::string& iq) {
  std::unique_ptr<base::DictionaryValue> message(new base::DictionaryValue());
  message->SetString("iq", iq);
  message->SetString("type", "sendOutgoingIq");
  SendMessageToClient(std::move(message));
}

void It2MeNativeMessagingHost::SendErrorAndExit(
    std::unique_ptr<base::DictionaryValue> response,
    const std::string& description) const {
  DCHECK(task_runner()->BelongsToCurrentThread());

  LOG(ERROR) << description;

  response->SetString("type", "error");
  response->SetString("description", description);
  SendMessageToClient(std::move(response));

  // Trigger a host shutdown by sending an empty message.
  client_->CloseChannel(std::string());
}

void It2MeNativeMessagingHost::SendPolicyErrorAndExit() const {
  DCHECK(task_runner()->BelongsToCurrentThread());

  auto message = base::MakeUnique<base::DictionaryValue>();
  message->SetString("type", "policyError");
  SendMessageToClient(std::move(message));
  client_->CloseChannel(std::string());
}

void It2MeNativeMessagingHost::OnStateChanged(
    It2MeHostState state,
    const std::string& error_message) {
  DCHECK(task_runner()->BelongsToCurrentThread());

  state_ = state;

  std::unique_ptr<base::DictionaryValue> message(new base::DictionaryValue());

  message->SetString("type", "hostStateChanged");
  message->SetString("state", HostStateToString(state));

  switch (state_) {
    case kReceivedAccessCode:
      message->SetString("accessCode", access_code_);
      message->SetInteger("accessCodeLifetime",
                          access_code_lifetime_.InSeconds());
      break;

    case kConnected:
      message->SetString("client", client_username_);
      break;

    case kDisconnected:
      client_username_.clear();
      break;

    case kError:
      // kError is an internal-only state, sent to the web-app by a separate
      // "error" message so that errors that occur before the "connect" message
      // is sent can be communicated.
      message->SetString("type", "error");
      message->SetString("description", error_message);
      break;

    default:
      break;
  }

  SendMessageToClient(std::move(message));
}

void It2MeNativeMessagingHost::SetPolicyErrorClosureForTesting(
    const base::Closure& closure) {
  policy_error_closure_for_testing_ = closure;
}

void It2MeNativeMessagingHost::OnNatPolicyChanged(bool nat_traversal_enabled) {
  DCHECK(task_runner()->BelongsToCurrentThread());

  std::unique_ptr<base::DictionaryValue> message(new base::DictionaryValue());

  message->SetString("type", "natPolicyChanged");
  message->SetBoolean("natTraversalEnabled", nat_traversal_enabled);
  SendMessageToClient(std::move(message));
}

// Stores the Access Code for the web-app to query.
void It2MeNativeMessagingHost::OnStoreAccessCode(
    const std::string& access_code,
    base::TimeDelta access_code_lifetime) {
  DCHECK(task_runner()->BelongsToCurrentThread());

  access_code_ = access_code;
  access_code_lifetime_ = access_code_lifetime;
}

// Stores the client user's name for the web-app to query.
void It2MeNativeMessagingHost::OnClientAuthenticated(
    const std::string& client_username) {
  DCHECK(task_runner()->BelongsToCurrentThread());

  client_username_ = client_username;
}

scoped_refptr<base::SingleThreadTaskRunner>
It2MeNativeMessagingHost::task_runner() const {
  return host_context_->ui_task_runner();
}

/* static */
std::string It2MeNativeMessagingHost::HostStateToString(
    It2MeHostState host_state) {
  return ValueToName(kIt2MeHostStates, host_state);
}

void It2MeNativeMessagingHost::OnPolicyUpdate(
    std::unique_ptr<base::DictionaryValue> policies) {
  // Don't dynamically change the elevation status since we don't have a good
  // way to communicate changes to the user.
  if (!policy_received_) {
    bool allow_elevated_host = false;
    if (!policies->GetBoolean(
            policy::key::kRemoteAccessHostAllowUiAccessForRemoteAssistance,
            &allow_elevated_host)) {
      LOG(WARNING) << "Failed to retrieve elevated host policy value.";
    }
#if defined(OS_WIN)
    LOG(INFO) << "Allow UiAccess for Remote Assistance: "
              << allow_elevated_host;
#endif  // defined(OS_WIN)

    policy_received_ = true;

    // If |allow_elevated_host| is false, then we will fall back to using a host
    // running in the current context regardless of the elevation request.  This
    // may not be ideal, but is still functional.
    needs_elevation_ = needs_elevation_ && allow_elevated_host;
    if (pending_connect_) {
      base::ResetAndReturn(&pending_connect_).Run();
    }
  }

  if (it2me_host_) {
    it2me_host_->OnPolicyUpdate(std::move(policies));
  }
}

void It2MeNativeMessagingHost::OnPolicyError() {
  LOG(ERROR) << "Malformed policies detected.";
  policy_received_ = true;

  if (policy_error_closure_for_testing_) {
    policy_error_closure_for_testing_.Run();
  }

  if (it2me_host_) {
    // If there is already a connection, close it and notify the webapp.
    it2me_host_->Disconnect();
    it2me_host_ = nullptr;
    SendPolicyErrorAndExit();
  } else if (pending_connect_) {
    // If there is no connection, run the pending connection callback if there
    // is one, but otherwise do nothing. The policy error will be sent when a
    // connection is made; doing so beforehand would break assumptions made by
    // the Chrome app.
    base::ResetAndReturn(&pending_connect_).Run();
  }
}

#if defined(OS_WIN)

bool It2MeNativeMessagingHost::DelegateToElevatedHost(
    std::unique_ptr<base::DictionaryValue> message) {
  DCHECK(task_runner()->BelongsToCurrentThread());
  DCHECK(needs_elevation_);

  if (!elevated_host_) {
    base::FilePath binary_path =
        base::CommandLine::ForCurrentProcess()->GetProgram();
    CHECK(binary_path.BaseName() == base::FilePath(kBaseHostBinaryName));

    // The new process runs at an elevated level due to being granted uiAccess.
    // |parent_window_handle| can be used to position dialog windows but is not
    // currently used.
    elevated_host_.reset(new ElevatedNativeMessagingHost(
        binary_path.DirName().Append(kElevatedHostBinaryName),
        /*parent_window_handle=*/0,
        /*elevate_process=*/false,
        /*host_timeout=*/base::TimeDelta(), client_));
  }

  if (elevated_host_->EnsureElevatedHostCreated()) {
    elevated_host_->SendMessage(std::move(message));
    return true;
  }

  return false;
}

#else  // !defined(OS_WIN)

bool It2MeNativeMessagingHost::DelegateToElevatedHost(
    std::unique_ptr<base::DictionaryValue> message) {
  NOTREACHED();
  return false;
}

#endif  // !defined(OS_WIN)

}  // namespace remoting
