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

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/initialize_extensions_client.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/service_manager_connection.h"
#include "extensions/browser/extension_file_task_runner.h"
#include "extensions/browser/sandboxed_unpacker.h"
#include "extensions/common/extension.h"
#include "extensions/common/verifier_formats.h"
#include "services/service_manager/public/cpp/connector.h"

using content::BrowserThread;

namespace extensions {

namespace {

void PrintPackExtensionMessage(const std::string& message) {
  VLOG(1) << message;
}

}  // namespace

StartupHelper::StartupHelper() : pack_job_succeeded_(false) {
  EnsureExtensionsClientInitialized();
}

void StartupHelper::OnPackSuccess(
    const base::FilePath& crx_path,
    const base::FilePath& output_private_key_path) {
  pack_job_succeeded_ = true;
  PrintPackExtensionMessage(
      base::UTF16ToUTF8(
          PackExtensionJob::StandardSuccessMessage(crx_path,
                                                   output_private_key_path)));
}

void StartupHelper::OnPackFailure(const std::string& error_message,
                                  ExtensionCreator::ErrorType type) {
  PrintPackExtensionMessage(error_message);
}

bool StartupHelper::PackExtension(const base::CommandLine& cmd_line) {
  if (!cmd_line.HasSwitch(::switches::kPackExtension))
    return false;

  // Input Paths.
  base::FilePath src_dir =
      cmd_line.GetSwitchValuePath(::switches::kPackExtension);
  base::FilePath private_key_path;
  if (cmd_line.HasSwitch(::switches::kPackExtensionKey)) {
    private_key_path =
        cmd_line.GetSwitchValuePath(::switches::kPackExtensionKey);
  }

  // Launch a job to perform the packing on the blocking thread.  Ignore
  // warnings from the packing process. (e.g. Overwrite any existing crx file.)
  PackExtensionJob pack_job(this, src_dir, private_key_path,
                            ExtensionCreator::kOverwriteCRX);
  pack_job.set_synchronous();
  pack_job.Start();

  return pack_job_succeeded_;
}

namespace {

class ValidateCrxHelper : public SandboxedUnpackerClient {
 public:
  ValidateCrxHelper(const CRXFileInfo& file,
                    const base::FilePath& temp_dir,
                    base::OnceClosure quit_closure)
      : crx_file_(file),
        temp_dir_(temp_dir),
        quit_closure_(std::move(quit_closure)),
        success_(false) {}

  bool success() const { return success_; }
  const base::string16& error() const { return error_; }

  void Start() {
    std::unique_ptr<::service_manager::Connector> connector =
        content::ServiceManagerConnection::GetForProcess()
            ->GetConnector()
            ->Clone();
    GetExtensionFileTaskRunner()->PostTask(
        FROM_HERE, base::BindOnce(&ValidateCrxHelper::StartOnBlockingThread,
                                  this, std::move(connector)));
  }

 protected:
  ~ValidateCrxHelper() override {}

  void OnUnpackSuccess(
      const base::FilePath& temp_dir,
      const base::FilePath& extension_root,
      std::unique_ptr<base::DictionaryValue> original_manifest,
      const Extension* extension,
      const SkBitmap& install_icon,
      const base::Optional<int>& dnr_ruleset_checksum) override {
    DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence());
    success_ = true;
    base::PostTaskWithTraits(
        FROM_HERE, {BrowserThread::UI},
        base::BindOnce(&ValidateCrxHelper::FinishOnUIThread, this));
  }

  void OnUnpackFailure(const CrxInstallError& error) override {
    DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence());
    success_ = false;
    error_ = error.message();
    base::PostTaskWithTraits(
        FROM_HERE, {BrowserThread::UI},
        base::BindOnce(&ValidateCrxHelper::FinishOnUIThread, this));
  }

  void FinishOnUIThread() {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    std::move(quit_closure_).Run();
  }

  void StartOnBlockingThread(
      std::unique_ptr<service_manager::Connector> connector) {
    DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence());
    auto unpacker = base::MakeRefCounted<SandboxedUnpacker>(
        std::move(connector), Manifest::INTERNAL,
        0, /* no special creation flags */
        temp_dir_, GetExtensionFileTaskRunner().get(), this);
    unpacker->StartWithCrx(crx_file_);
  }

  // The file being validated.
  const CRXFileInfo& crx_file_;

  // The temporary directory where the sandboxed unpacker will do work.
  const base::FilePath& temp_dir_;

  // Closure called upon completion.
  base::OnceClosure quit_closure_;

  // Whether the unpacking was successful.
  bool success_;

  // If the unpacking wasn't successful, this contains an error message.
  base::string16 error_;

 private:
  DISALLOW_COPY_AND_ASSIGN(ValidateCrxHelper);
};

}  // namespace

bool StartupHelper::ValidateCrx(const base::CommandLine& cmd_line,
                                std::string* error) {
  CHECK(error);
  base::FilePath path = cmd_line.GetSwitchValuePath(::switches::kValidateCrx);
  if (path.empty()) {
    *error = base::StringPrintf("Empty path passed for %s",
                                ::switches::kValidateCrx);
    return false;
  }
  base::ScopedTempDir temp_dir;

  if (!temp_dir.CreateUniqueTempDir()) {
    *error = std::string("Failed to create temp dir");
    return false;
  }

  base::RunLoop run_loop;
  CRXFileInfo file(path, extensions::GetExternalVerifierFormat());
  auto helper = base::MakeRefCounted<ValidateCrxHelper>(
      file, temp_dir.GetPath(), run_loop.QuitClosure());
  helper->Start();
  run_loop.Run();

  bool success = helper->success();
  if (!success)
    *error = base::UTF16ToUTF8(helper->error());
  return success;
}

StartupHelper::~StartupHelper() {}

}  // namespace extensions
