// 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 "chrome/browser/component_updater/component_patcher_operation.h"

#include <string>
#include <vector>

#include "base/bind.h"
#include "base/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/json/json_file_value_serializer.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/component_updater/component_patcher.h"
#include "chrome/browser/component_updater/component_updater_service.h"
#include "chrome/common/chrome_utility_messages.h"
#include "chrome/common/extensions/extension_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/utility_process_host.h"
#include "courgette/courgette.h"
#include "courgette/third_party/bsdiff.h"
#include "crypto/secure_hash.h"
#include "crypto/sha2.h"
#include "crypto/signature_verifier.h"
#include "extensions/common/crx_file.h"
#include "ipc/ipc_message_macros.h"

using crypto::SecureHash;

namespace component_updater {

namespace {

const char kInput[] = "input";
const char kOp[] = "op";
const char kOutput[] = "output";
const char kPatch[] = "patch";
const char kSha256[] = "sha256";

// The integer offset disambiguates between overlapping error ranges.
const int kCourgetteErrorOffset = 300;
const int kBsdiffErrorOffset = 600;

class CourgetteTraits : public DeltaUpdateOpPatchStrategy {
 public:
  virtual int GetErrorOffset() const OVERRIDE;
  virtual int GetSuccessCode() const OVERRIDE;
  virtual scoped_ptr<IPC::Message> GetPatchMessage(
      base::FilePath input_abs_path,
      base::FilePath patch_abs_path,
      base::FilePath output_abs_path) OVERRIDE;
  virtual int Patch(base::FilePath input_abs_path,
                    base::FilePath patch_abs_path,
                    base::FilePath output_abs_path) OVERRIDE;
};

int CourgetteTraits::GetErrorOffset() const {
  return kCourgetteErrorOffset;
}

int CourgetteTraits::GetSuccessCode() const {
  return courgette::C_OK;
}

scoped_ptr<IPC::Message> CourgetteTraits::GetPatchMessage(
    base::FilePath input_abs_path,
    base::FilePath patch_abs_path,
    base::FilePath output_abs_path) {
  return scoped_ptr<IPC::Message>(
      new ChromeUtilityMsg_PatchFileCourgette(input_abs_path,
                                              patch_abs_path,
                                              output_abs_path));
}

int CourgetteTraits::Patch(base::FilePath input_abs_path,
                           base::FilePath patch_abs_path,
                           base::FilePath output_abs_path) {
  return courgette::ApplyEnsemblePatch(input_abs_path.value().c_str(),
                                       patch_abs_path.value().c_str(),
                                       output_abs_path.value().c_str());
}

class BsdiffTraits : public DeltaUpdateOpPatchStrategy {
 public:
  virtual int GetErrorOffset() const OVERRIDE;
  virtual int GetSuccessCode() const OVERRIDE;
  virtual scoped_ptr<IPC::Message> GetPatchMessage(
      base::FilePath input_abs_path,
      base::FilePath patch_abs_path,
      base::FilePath output_abs_path) OVERRIDE;
  virtual int Patch(base::FilePath input_abs_path,
                    base::FilePath patch_abs_path,
                    base::FilePath output_abs_path) OVERRIDE;
};

int BsdiffTraits::GetErrorOffset() const {
  return kBsdiffErrorOffset;
}

int BsdiffTraits::GetSuccessCode() const {
  return courgette::OK;
}

scoped_ptr<IPC::Message> BsdiffTraits::GetPatchMessage(
    base::FilePath input_abs_path,
    base::FilePath patch_abs_path,
    base::FilePath output_abs_path) {
  return scoped_ptr<IPC::Message>(
      new ChromeUtilityMsg_PatchFileBsdiff(input_abs_path,
                                           patch_abs_path,
                                           output_abs_path));
}

int BsdiffTraits::Patch(base::FilePath input_abs_path,
                        base::FilePath patch_abs_path,
                        base::FilePath output_abs_path) {
  return courgette::ApplyBinaryPatch(input_abs_path,
                                     patch_abs_path,
                                     output_abs_path);
}

}  // namespace

DeltaUpdateOpPatchStrategy::~DeltaUpdateOpPatchStrategy() {
}

DeltaUpdateOp* CreateDeltaUpdateOp(const std::string& operation) {
  if (operation == "copy") {
    return new DeltaUpdateOpCopy();
  } else if (operation == "create") {
    return new DeltaUpdateOpCreate();
  } else if (operation == "bsdiff") {
    scoped_ptr<DeltaUpdateOpPatchStrategy> strategy(new BsdiffTraits());
    return new DeltaUpdateOpPatch(strategy.Pass());
  } else if (operation == "courgette") {
    scoped_ptr<DeltaUpdateOpPatchStrategy> strategy(new CourgetteTraits());
    return new DeltaUpdateOpPatch(strategy.Pass());
  }
  return NULL;
}

DeltaUpdateOp* CreateDeltaUpdateOp(const base::DictionaryValue& command) {
  std::string operation;
  if (!command.GetString(kOp, &operation))
    return NULL;
  return CreateDeltaUpdateOp(operation);
}

DeltaUpdateOp::DeltaUpdateOp() : in_process_(false) {
}

DeltaUpdateOp::~DeltaUpdateOp() {
}

void DeltaUpdateOp::Run(const base::DictionaryValue* command_args,
                        const base::FilePath& input_dir,
                        const base::FilePath& unpack_dir,
                        ComponentInstaller* installer,
                        bool in_process,
                        const ComponentUnpacker::Callback& callback,
                        scoped_refptr<base::SequencedTaskRunner> task_runner) {
  callback_ = callback;
  in_process_ = in_process;
  task_runner_ = task_runner;
  std::string output_rel_path;
  if (!command_args->GetString(kOutput, &output_rel_path) ||
      !command_args->GetString(kSha256, &output_sha256_)) {
    DoneRunning(ComponentUnpacker::kDeltaBadCommands, 0);
    return;
  }

  output_abs_path_ =
      unpack_dir.Append(base::FilePath::FromUTF8Unsafe(output_rel_path));
  ComponentUnpacker::Error parse_result =
      DoParseArguments(command_args, input_dir, installer);
  if (parse_result != ComponentUnpacker::kNone) {
    DoneRunning(parse_result, 0);
    return;
  }

  const base::FilePath parent = output_abs_path_.DirName();
  if (!base::DirectoryExists(parent)) {
    if (!base::CreateDirectory(parent)) {
      DoneRunning(ComponentUnpacker::kIoError, 0);
      return;
    }
  }

  DoRun(base::Bind(&DeltaUpdateOp::DoneRunning,
                   scoped_refptr<DeltaUpdateOp>(this)));
}

void DeltaUpdateOp::DoneRunning(ComponentUnpacker::Error error,
                                int extended_error) {
  if (error == ComponentUnpacker::kNone)
    error = CheckHash();
  task_runner_->PostTask(FROM_HERE,
                         base::Bind(callback_, error, extended_error));
  callback_.Reset();
}

// Uses the hash as a checksum to confirm that the file now residing in the
// output directory probably has the contents it should.
ComponentUnpacker::Error DeltaUpdateOp::CheckHash() {
  std::vector<uint8> expected_hash;
  if (!base::HexStringToBytes(output_sha256_, &expected_hash) ||
      expected_hash.size() != crypto::kSHA256Length)
    return ComponentUnpacker::kDeltaVerificationFailure;

  base::MemoryMappedFile output_file_mmapped;
  if (!output_file_mmapped.Initialize(output_abs_path_))
    return ComponentUnpacker::kDeltaVerificationFailure;

  uint8 actual_hash[crypto::kSHA256Length] = {0};
  const scoped_ptr<SecureHash> hasher(SecureHash::Create(SecureHash::SHA256));
  hasher->Update(output_file_mmapped.data(), output_file_mmapped.length());
  hasher->Finish(actual_hash, sizeof(actual_hash));
  if (memcmp(actual_hash, &expected_hash[0], sizeof(actual_hash)))
    return ComponentUnpacker::kDeltaVerificationFailure;

  return ComponentUnpacker::kNone;
}

bool DeltaUpdateOp::InProcess() {
  return in_process_;
}

scoped_refptr<base::SequencedTaskRunner> DeltaUpdateOp::GetTaskRunner() {
  return task_runner_;
}

DeltaUpdateOpCopy::DeltaUpdateOpCopy() {
}

DeltaUpdateOpCopy::~DeltaUpdateOpCopy() {
}

ComponentUnpacker::Error DeltaUpdateOpCopy::DoParseArguments(
    const base::DictionaryValue* command_args,
    const base::FilePath& input_dir,
    ComponentInstaller* installer) {
  std::string input_rel_path;
  if (!command_args->GetString(kInput, &input_rel_path))
    return ComponentUnpacker::kDeltaBadCommands;

  if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
    return ComponentUnpacker::kDeltaMissingExistingFile;

  return ComponentUnpacker::kNone;
}

void DeltaUpdateOpCopy::DoRun(const ComponentUnpacker::Callback& callback) {
  if (!base::CopyFile(input_abs_path_, output_abs_path_))
    callback.Run(ComponentUnpacker::kDeltaOperationFailure, 0);
  else
    callback.Run(ComponentUnpacker::kNone, 0);
}

DeltaUpdateOpCreate::DeltaUpdateOpCreate() {
}

DeltaUpdateOpCreate::~DeltaUpdateOpCreate() {
}

ComponentUnpacker::Error DeltaUpdateOpCreate::DoParseArguments(
    const base::DictionaryValue* command_args,
    const base::FilePath& input_dir,
    ComponentInstaller* installer) {
  std::string patch_rel_path;
  if (!command_args->GetString(kPatch, &patch_rel_path))
    return ComponentUnpacker::kDeltaBadCommands;

  patch_abs_path_ =
      input_dir.Append(base::FilePath::FromUTF8Unsafe(patch_rel_path));

  return ComponentUnpacker::kNone;
}

void DeltaUpdateOpCreate::DoRun(const ComponentUnpacker::Callback& callback) {
  if (!base::Move(patch_abs_path_, output_abs_path_))
    callback.Run(ComponentUnpacker::kDeltaOperationFailure, 0);
  else
    callback.Run(ComponentUnpacker::kNone, 0);
}

DeltaUpdateOpPatchHost::DeltaUpdateOpPatchHost(
    scoped_refptr<DeltaUpdateOpPatch> patcher,
    scoped_refptr<base::SequencedTaskRunner> task_runner)
    : patcher_(patcher), task_runner_(task_runner) {
}

DeltaUpdateOpPatchHost::~DeltaUpdateOpPatchHost() {
}

void DeltaUpdateOpPatchHost::StartProcess(scoped_ptr<IPC::Message> message) {
  // The DeltaUpdateOpPatchHost is not responsible for deleting the
  // UtilityProcessHost object.
  content::UtilityProcessHost* host = content::UtilityProcessHost::Create(
      this, base::MessageLoopProxy::current().get());
  host->DisableSandbox();
  host->Send(message.release());
}

bool DeltaUpdateOpPatchHost::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(DeltaUpdateOpPatchHost, message)
    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PatchFile_Succeeded,
                        OnPatchSucceeded)
    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PatchFile_Failed,
                        OnPatchFailed)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void DeltaUpdateOpPatchHost::OnPatchSucceeded() {
  task_runner_->PostTask(FROM_HERE,
                         base::Bind(&DeltaUpdateOpPatch::DonePatching,
                                    patcher_,
                                    ComponentUnpacker::kNone,
                                    0));
  task_runner_ = NULL;
  patcher_ = NULL;
}

void DeltaUpdateOpPatchHost::OnPatchFailed(int error_code) {
  task_runner_->PostTask(FROM_HERE,
                         base::Bind(&DeltaUpdateOpPatch::DonePatching,
                                    patcher_,
                                    ComponentUnpacker::kDeltaOperationFailure,
                                    error_code));
  task_runner_ = NULL;
  patcher_ = NULL;
}

void DeltaUpdateOpPatchHost::OnProcessCrashed(int exit_code) {
  task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&DeltaUpdateOpPatch::DonePatching,
                 patcher_,
                 ComponentUnpacker::kDeltaPatchProcessFailure,
                 exit_code));
  task_runner_ = NULL;
  patcher_ = NULL;
}

DeltaUpdateOpPatch::DeltaUpdateOpPatch(
    scoped_ptr<DeltaUpdateOpPatchStrategy> strategy) {
  strategy_ = strategy.Pass();
}

DeltaUpdateOpPatch::~DeltaUpdateOpPatch() {
}

ComponentUnpacker::Error DeltaUpdateOpPatch::DoParseArguments(
    const base::DictionaryValue* command_args,
    const base::FilePath& input_dir,
    ComponentInstaller* installer) {
  std::string patch_rel_path;
  std::string input_rel_path;
  if (!command_args->GetString(kPatch, &patch_rel_path) ||
      !command_args->GetString(kInput, &input_rel_path))
    return ComponentUnpacker::kDeltaBadCommands;

  if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
    return ComponentUnpacker::kDeltaMissingExistingFile;

  patch_abs_path_ =
      input_dir.Append(base::FilePath::FromUTF8Unsafe(patch_rel_path));

  return ComponentUnpacker::kNone;
}

void DeltaUpdateOpPatch::DoRun(const ComponentUnpacker::Callback& callback) {
  callback_ = callback;
  if (!InProcess()) {
    host_ = new DeltaUpdateOpPatchHost(scoped_refptr<DeltaUpdateOpPatch>(this),
                                       GetTaskRunner());
    content::BrowserThread::PostTask(
        content::BrowserThread::IO,
        FROM_HERE,
        base::Bind(&DeltaUpdateOpPatchHost::StartProcess,
                   host_,
                   base::Passed(strategy_->GetPatchMessage(input_abs_path_,
                                                           patch_abs_path_,
                                                           output_abs_path_))));
    return;
  }
  const int result = strategy_->Patch(input_abs_path_,
                                      patch_abs_path_,
                                      output_abs_path_);
  if (result == strategy_->GetSuccessCode())
    DonePatching(ComponentUnpacker::kNone, 0);
  else
    DonePatching(ComponentUnpacker::kDeltaOperationFailure, result);
}

void DeltaUpdateOpPatch::DonePatching(ComponentUnpacker::Error error,
                                      int error_code) {
  host_ = NULL;
  if (error != ComponentUnpacker::kNone) {
    error_code += strategy_->GetErrorOffset();
  }
  callback_.Run(error, error_code);
  // The callback is no longer needed - it is best to release it in case it
  // contains a reference to this object.
  callback_.Reset();
}

}  // namespace component_updater
