// Copyright (c) 2012 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 "chrome/browser/extensions/api/messaging/native_message_process_host.h"

#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/prefs/pref_service.h"
#include "base/process/kill.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h"
#include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
#include "chrome/common/chrome_version_info.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/pref_names.h"
#include "extensions/common/constants.h"
#include "extensions/common/features/feature.h"
#include "net/base/file_stream.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
#include "url/gurl.h"

namespace {

// Maximum message size in bytes for messages received from Native Messaging
// hosts. Message size is limited mainly to prevent Chrome from crashing when
// native application misbehaves (e.g. starts writing garbage to the pipe).
const size_t kMaximumMessageSize = 1024 * 1024;

// Message header contains 4-byte integer size of the message.
const size_t kMessageHeaderSize = 4;

// Size of the buffer to be allocated for each read.
const size_t kReadBufferSize = 4096;

const char kFailedToStartError[] = "Failed to start native messaging host.";
const char kInvalidNameError[] =
    "Invalid native messaging host name specified.";
const char kNativeHostExited[] = "Native host has exited.";
const char kNotFoundError[] = "Specified native messaging host not found.";
const char kForbiddenError[] =
    "Access to the specified native messaging host is forbidden.";
const char kHostInputOuputError[] =
    "Error when communicating with the native messaging host.";

}  // namespace

namespace extensions {

// static
NativeMessageProcessHost::PolicyPermission
NativeMessageProcessHost::IsHostAllowed(const PrefService* pref_service,
                                        const std::string& native_host_name) {
  NativeMessageProcessHost::PolicyPermission allow_result = ALLOW_ALL;
  if (pref_service->IsManagedPreference(
          pref_names::kNativeMessagingUserLevelHosts)) {
    if (!pref_service->GetBoolean(pref_names::kNativeMessagingUserLevelHosts))
      allow_result = ALLOW_SYSTEM_ONLY;
  }

  // All native messaging hosts are allowed if there is no blacklist.
  if (!pref_service->IsManagedPreference(pref_names::kNativeMessagingBlacklist))
    return allow_result;
  const base::ListValue* blacklist =
      pref_service->GetList(pref_names::kNativeMessagingBlacklist);
  if (!blacklist)
    return allow_result;

  // Check if the name or the wildcard is in the blacklist.
  base::StringValue name_value(native_host_name);
  base::StringValue wildcard_value("*");
  if (blacklist->Find(name_value) == blacklist->end() &&
      blacklist->Find(wildcard_value) == blacklist->end()) {
    return allow_result;
  }

  // The native messaging host is blacklisted. Check the whitelist.
  if (pref_service->IsManagedPreference(
          pref_names::kNativeMessagingWhitelist)) {
    const base::ListValue* whitelist =
        pref_service->GetList(pref_names::kNativeMessagingWhitelist);
    if (whitelist && whitelist->Find(name_value) != whitelist->end())
      return allow_result;
  }

  return DISALLOW;
}

NativeMessageProcessHost::NativeMessageProcessHost(
    base::WeakPtr<Client> weak_client_ui,
    const std::string& source_extension_id,
    const std::string& native_host_name,
    int destination_port,
    scoped_ptr<NativeProcessLauncher> launcher)
    : weak_client_ui_(weak_client_ui),
      source_extension_id_(source_extension_id),
      native_host_name_(native_host_name),
      destination_port_(destination_port),
      launcher_(launcher.Pass()),
      closed_(false),
      process_handle_(base::kNullProcessHandle),
#if defined(OS_POSIX)
      read_file_(-1),
#endif
      read_pending_(false),
      write_pending_(false) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // It's safe to use base::Unretained() here because NativeMessagePort always
  // deletes us on the IO thread.
  content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
      base::Bind(&NativeMessageProcessHost::LaunchHostProcess,
                 base::Unretained(this)));
}

NativeMessageProcessHost::~NativeMessageProcessHost() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  Close(std::string());
}

// static
scoped_ptr<NativeMessageProcessHost> NativeMessageProcessHost::Create(
    gfx::NativeView native_view,
    base::WeakPtr<Client> weak_client_ui,
    const std::string& source_extension_id,
    const std::string& native_host_name,
    int destination_port,
    bool allow_user_level) {
  return CreateWithLauncher(weak_client_ui, source_extension_id,
                            native_host_name, destination_port,
                            NativeProcessLauncher::CreateDefault(
                                allow_user_level, native_view));
}

// static
scoped_ptr<NativeMessageProcessHost>
NativeMessageProcessHost::CreateWithLauncher(
    base::WeakPtr<Client> weak_client_ui,
    const std::string& source_extension_id,
    const std::string& native_host_name,
    int destination_port,
    scoped_ptr<NativeProcessLauncher> launcher) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  scoped_ptr<NativeMessageProcessHost> process(new NativeMessageProcessHost(
      weak_client_ui, source_extension_id, native_host_name,
      destination_port, launcher.Pass()));

  return process.Pass();
}

void NativeMessageProcessHost::LaunchHostProcess() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  GURL origin(std::string(kExtensionScheme) + "://" + source_extension_id_);
  launcher_->Launch(origin, native_host_name_,
                    base::Bind(&NativeMessageProcessHost::OnHostProcessLaunched,
                               base::Unretained(this)));
}

void NativeMessageProcessHost::OnHostProcessLaunched(
    NativeProcessLauncher::LaunchResult result,
    base::ProcessHandle process_handle,
    base::File read_file,
    base::File write_file) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  switch (result) {
    case NativeProcessLauncher::RESULT_INVALID_NAME:
      Close(kInvalidNameError);
      return;
    case NativeProcessLauncher::RESULT_NOT_FOUND:
      Close(kNotFoundError);
      return;
    case NativeProcessLauncher::RESULT_FORBIDDEN:
      Close(kForbiddenError);
      return;
    case NativeProcessLauncher::RESULT_FAILED_TO_START:
      Close(kFailedToStartError);
      return;
    case NativeProcessLauncher::RESULT_SUCCESS:
      break;
  }

  process_handle_ = process_handle;
#if defined(OS_POSIX)
  // This object is not the owner of the file so it should not keep an fd.
  read_file_ = read_file.GetPlatformFile();
#endif

  scoped_refptr<base::TaskRunner> task_runner(
      content::BrowserThread::GetBlockingPool()->
          GetTaskRunnerWithShutdownBehavior(
              base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));

  read_stream_.reset(new net::FileStream(read_file.Pass(), task_runner));
  write_stream_.reset(new net::FileStream(write_file.Pass(), task_runner));

  WaitRead();
  DoWrite();
}

void NativeMessageProcessHost::Send(const std::string& json) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  if (closed_)
    return;

  // Allocate new buffer for the message.
  scoped_refptr<net::IOBufferWithSize> buffer =
      new net::IOBufferWithSize(json.size() + kMessageHeaderSize);

  // Copy size and content of the message to the buffer.
  COMPILE_ASSERT(sizeof(uint32) == kMessageHeaderSize, incorrect_header_size);
  *reinterpret_cast<uint32*>(buffer->data()) = json.size();
  memcpy(buffer->data() + kMessageHeaderSize, json.data(), json.size());

  // Push new message to the write queue.
  write_queue_.push(buffer);

  // Send() may be called before the host process is started. In that case the
  // message will be written when OnHostProcessLaunched() is called. If it's
  // already started then write the message now.
  if (write_stream_)
    DoWrite();
}

#if defined(OS_POSIX)
void NativeMessageProcessHost::OnFileCanReadWithoutBlocking(int fd) {
  DCHECK_EQ(fd, read_file_);
  DoRead();
}

void NativeMessageProcessHost::OnFileCanWriteWithoutBlocking(int fd) {
  NOTREACHED();
}
#endif  // !defined(OS_POSIX)

void NativeMessageProcessHost::ReadNowForTesting() {
  DoRead();
}

void NativeMessageProcessHost::WaitRead() {
  if (closed_)
    return;

  DCHECK(!read_pending_);

  // On POSIX FileStream::Read() uses blocking thread pool, so it's better to
  // wait for the file to become readable before calling DoRead(). Otherwise it
  // would always be consuming one thread in the thread pool. On Windows
  // FileStream uses overlapped IO, so that optimization isn't necessary there.
#if defined(OS_POSIX)
  base::MessageLoopForIO::current()->WatchFileDescriptor(
    read_file_, false /* persistent */,
    base::MessageLoopForIO::WATCH_READ, &read_watcher_, this);
#else  // defined(OS_POSIX)
  DoRead();
#endif  // defined(!OS_POSIX)
}

void NativeMessageProcessHost::DoRead() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  while (!closed_ && !read_pending_) {
    read_buffer_ = new net::IOBuffer(kReadBufferSize);
    int result = read_stream_->Read(
        read_buffer_.get(),
        kReadBufferSize,
        base::Bind(&NativeMessageProcessHost::OnRead, base::Unretained(this)));
    HandleReadResult(result);
  }
}

void NativeMessageProcessHost::OnRead(int result) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
  DCHECK(read_pending_);
  read_pending_ = false;

  HandleReadResult(result);
  WaitRead();
}

void NativeMessageProcessHost::HandleReadResult(int result) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  if (closed_)
    return;

  if (result > 0) {
    ProcessIncomingData(read_buffer_->data(), result);
  } else if (result == net::ERR_IO_PENDING) {
    read_pending_ = true;
  } else if (result == 0 || result == net::ERR_CONNECTION_RESET) {
    // On Windows we get net::ERR_CONNECTION_RESET for a broken pipe, while on
    // Posix read() returns 0 in that case.
    Close(kNativeHostExited);
  } else {
    LOG(ERROR) << "Error when reading from Native Messaging host: " << result;
    Close(kHostInputOuputError);
  }
}

void NativeMessageProcessHost::ProcessIncomingData(
    const char* data, int data_size) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  incoming_data_.append(data, data_size);

  while (true) {
    if (incoming_data_.size() < kMessageHeaderSize)
      return;

    size_t message_size =
        *reinterpret_cast<const uint32*>(incoming_data_.data());

    if (message_size > kMaximumMessageSize) {
      LOG(ERROR) << "Native Messaging host tried sending a message that is "
                 << message_size << " bytes long.";
      Close(kHostInputOuputError);
      return;
    }

    if (incoming_data_.size() < message_size + kMessageHeaderSize)
      return;

    content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
        base::Bind(&Client::PostMessageFromNativeProcess, weak_client_ui_,
            destination_port_,
            incoming_data_.substr(kMessageHeaderSize, message_size)));

    incoming_data_.erase(0, kMessageHeaderSize + message_size);
  }
}

void NativeMessageProcessHost::DoWrite() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  while (!write_pending_ && !closed_) {
    if (!current_write_buffer_.get() ||
        !current_write_buffer_->BytesRemaining()) {
      if (write_queue_.empty())
        return;
      current_write_buffer_ = new net::DrainableIOBuffer(
          write_queue_.front().get(), write_queue_.front()->size());
      write_queue_.pop();
    }

    int result =
        write_stream_->Write(current_write_buffer_.get(),
                             current_write_buffer_->BytesRemaining(),
                             base::Bind(&NativeMessageProcessHost::OnWritten,
                                        base::Unretained(this)));
    HandleWriteResult(result);
  }
}

void NativeMessageProcessHost::HandleWriteResult(int result) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  if (result <= 0) {
    if (result == net::ERR_IO_PENDING) {
      write_pending_ = true;
    } else {
      LOG(ERROR) << "Error when writing to Native Messaging host: " << result;
      Close(kHostInputOuputError);
    }
    return;
  }

  current_write_buffer_->DidConsume(result);
}

void NativeMessageProcessHost::OnWritten(int result) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  DCHECK(write_pending_);
  write_pending_ = false;

  HandleWriteResult(result);
  DoWrite();
}

void NativeMessageProcessHost::Close(const std::string& error_message) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  if (!closed_) {
    closed_ = true;
    read_stream_.reset();
    write_stream_.reset();
    content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
        base::Bind(&Client::CloseChannel, weak_client_ui_,
                   destination_port_, error_message));
  }

  if (process_handle_ != base::kNullProcessHandle) {
    // Kill the host process if necessary to make sure we don't leave zombies.
    // On OSX base::EnsureProcessTerminated() may block, so we have to post a
    // task on the blocking pool.
#if defined(OS_MACOSX)
    content::BrowserThread::PostBlockingPoolTask(
        FROM_HERE, base::Bind(&base::EnsureProcessTerminated, process_handle_));
#else
    base::EnsureProcessTerminated(process_handle_);
#endif
    process_handle_ = base::kNullProcessHandle;
  }
}

}  // namespace extensions
