// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/updater/updater_module.h"

#include <utility>
#include <vector>

#include "base/bind_helpers.h"
#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/optional.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/post_task.h"
#include "base/task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/version.h"
#include "cobalt/browser/switches.h"
#include "cobalt/updater/crash_client.h"
#include "cobalt/updater/crash_reporter.h"
#include "cobalt/updater/utils.h"
#include "components/crx_file/crx_verifier.h"
#include "components/update_client/cobalt_slot_management.h"
#include "components/update_client/utils.h"
#include "starboard/common/file.h"
#include "starboard/configuration_constants.h"
#include "starboard/extension/installation_manager.h"

namespace {

using update_client::CobaltSlotManagement;
using update_client::ComponentState;

// The SHA256 hash of the "cobalt_evergreen_public" key.
constexpr uint8_t kCobaltPublicKeyHash[] = {
    0x51, 0xa8, 0xc0, 0x90, 0xf8, 0x1a, 0x14, 0xb0, 0xda, 0x7a, 0xfb,
    0x9e, 0x8b, 0x2d, 0x22, 0x65, 0x19, 0xb1, 0xfa, 0xba, 0x02, 0x04,
    0x3a, 0xb2, 0x7a, 0xf6, 0xfe, 0xd5, 0x35, 0xa1, 0x19, 0xd9};

void QuitLoop(base::OnceClosure quit_closure) { std::move(quit_closure).Run(); }

CobaltExtensionUpdaterNotificationState
ComponentStateToCobaltExtensionUpdaterNotificationState(
    ComponentState component_state) {
  switch (component_state) {
    case ComponentState::kChecking:
      return kCobaltExtensionUpdaterNotificationStateChecking;
    case ComponentState::kCanUpdate:
      return kCobaltExtensionUpdaterNotificationStateUpdateAvailable;
    case ComponentState::kDownloading:
      return kCobaltExtensionUpdaterNotificationStateDownloading;
    case ComponentState::kDownloaded:
      return kCobaltExtensionUpdaterNotificationStateDownloaded;
    case ComponentState::kUpdating:
      return kCobaltExtensionUpdaterNotificationStateInstalling;
#if SB_API_VERSION > 13
    case ComponentState::kUpdated:
      return kCobaltExtensionUpdaterNotificationStateUpdated;
    case ComponentState::kUpToDate:
      return kCobaltExtensionUpdaterNotificationStateUpToDate;
    case ComponentState::kUpdateError:
      return kCobaltExtensionUpdaterNotificationStateUpdateFailed;
#else
    case ComponentState::kUpdated:
      return kCobaltExtensionUpdaterNotificationStatekUpdated;
    case ComponentState::kUpToDate:
      return kCobaltExtensionUpdaterNotificationStatekUpToDate;
    case ComponentState::kUpdateError:
      return kCobaltExtensionUpdaterNotificationStatekUpdateFailed;
#endif
    default:
      return kCobaltExtensionUpdaterNotificationStateNone;
  }
}

}  // namespace

namespace cobalt {
namespace updater {

// The delay in seconds before the first update check.
const uint64_t kDefaultUpdateCheckDelaySeconds = 30;

void Observer::OnEvent(Events event, const std::string& id) {
  LOG(INFO) << "Observer::OnEvent id=" << id;
  std::string status;
  if (update_client_->GetCrxUpdateState(id, &crx_update_item_)) {
    auto status_iterator =
        component_to_updater_status_map.find(crx_update_item_.state);
    if (status_iterator == component_to_updater_status_map.end()) {
      status = "Status is unknown.";
    } else if (crx_update_item_.state == ComponentState::kUpToDate &&
               updater_configurator_->GetPreviousUpdaterStatus().compare(
                   updater_status_string_map.find(UpdaterStatus::kUpdated)
                       ->second) == 0) {
      status = std::string(
          updater_status_string_map.find(UpdaterStatus::kUpdated)->second);
    } else {
      status = std::string(
          updater_status_string_map.find(status_iterator->second)->second);
    }
    if (crx_update_item_.state == ComponentState::kUpdateError) {
      status +=
          ", error code is " + std::to_string(crx_update_item_.error_code);
    }
    if (updater_notification_ext_ != nullptr) {
      updater_notification_ext_->UpdaterState(
          ComponentStateToCobaltExtensionUpdaterNotificationState(
              crx_update_item_.state),
          GetCurrentEvergreenVersion().c_str());
    }
  } else {
    status = "No status available";
  }
  updater_configurator_->SetUpdaterStatus(status);
  LOG(INFO) << "Updater status is " << status;
}

UpdaterModule::UpdaterModule(network::NetworkModule* network_module,
                             uint64_t update_check_delay_sec)
    : network_module_(network_module),
      update_check_delay_sec_(update_check_delay_sec) {
  LOG(INFO) << "UpdaterModule::UpdaterModule";
  updater_thread_.reset(new base::Thread("Updater"));
  updater_thread_->StartWithOptions(
      base::Thread::Options(base::MessageLoop::TYPE_IO, 0));

  DETACH_FROM_THREAD(thread_checker_);
  // Initialize the underlying update client.
  is_updater_running_ = true;
  updater_thread_->task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&UpdaterModule::Initialize, base::Unretained(this)));
}

UpdaterModule::~UpdaterModule() {
  LOG(INFO) << "UpdaterModule::~UpdaterModule";
  if (is_updater_running_) {
    is_updater_running_ = false;
    updater_thread_->task_runner()->PostBlockingTask(
        FROM_HERE,
        base::Bind(&UpdaterModule::Finalize, base::Unretained(this)));
  }

  // Upon destruction the thread will allow all queued tasks to complete before
  // the thread is terminated. The thread is destroyed before returning from
  // this destructor to prevent one of the thread's tasks from accessing member
  // fields after they are destroyed.
  updater_thread_.reset();
}

void UpdaterModule::Suspend() {
  if (is_updater_running_) {
    is_updater_running_ = false;
    updater_thread_->task_runner()->PostBlockingTask(
        FROM_HERE,
        base::Bind(&UpdaterModule::Finalize, base::Unretained(this)));
  }
}

void UpdaterModule::Resume() {
  if (!is_updater_running_) {
    is_updater_running_ = true;
    updater_thread_->task_runner()->PostTask(
        FROM_HERE,
        base::Bind(&UpdaterModule::Initialize, base::Unretained(this)));
  }
}

void UpdaterModule::Initialize() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  updater_configurator_ = base::MakeRefCounted<Configurator>(network_module_);
  update_client_ = update_client::UpdateClientFactory(updater_configurator_);

  updater_observer_.reset(new Observer(update_client_, updater_configurator_));
  update_client_->AddObserver(updater_observer_.get());

  // Schedule the first update check.

  LOG(INFO) << "Scheduling UpdateCheck with delay " << update_check_delay_sec_
            << " seconds";
  updater_thread_->task_runner()->PostDelayedTask(
      FROM_HERE, base::Bind(&UpdaterModule::Update, base::Unretained(this)),
      base::TimeDelta::FromSeconds(update_check_delay_sec_));
}

void UpdaterModule::Finalize() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  LOG(INFO) << "UpdaterModule::Finalize begin";
  update_client_->RemoveObserver(updater_observer_.get());
  updater_observer_.reset();
  update_client_->Stop();
  update_client_ = nullptr;

  if (updater_configurator_ != nullptr) {
    auto pref_service = updater_configurator_->GetPrefService();
    if (pref_service != nullptr) {
      pref_service->CommitPendingWrite(
          base::BindOnce(&QuitLoop, base::Bind(base::DoNothing::Repeatedly())));
    }
  }

  updater_configurator_ = nullptr;

  // Cleanup drain files
  const auto installation_manager =
      static_cast<const CobaltExtensionInstallationManagerApi*>(
          SbSystemGetExtension(kCobaltExtensionInstallationManagerName));
  if (installation_manager) {
    CobaltSlotManagement cobalt_slot_management;
    if (cobalt_slot_management.Init(installation_manager)) {
      cobalt_slot_management.CleanupAllDrainFiles();
    }
  }
  LOG(INFO) << "UpdaterModule::Finalize end";
}

void UpdaterModule::MarkSuccessful() {
  updater_thread_->task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&UpdaterModule::MarkSuccessfulImpl, base::Unretained(this)));
}

void UpdaterModule::MarkSuccessfulImpl() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  LOG(INFO) << "UpdaterModule::MarkSuccessfulImpl";

  auto installation_manager =
      static_cast<const CobaltExtensionInstallationManagerApi*>(
          SbSystemGetExtension(kCobaltExtensionInstallationManagerName));
  if (!installation_manager) {
    LOG(ERROR) << "Updater failed to get installation manager extension.";
    return;
  }
  int index = installation_manager->GetCurrentInstallationIndex();
  if (index == IM_EXT_ERROR) {
    LOG(ERROR) << "Updater failed to get current installation index.";
    return;
  }
  if (installation_manager->MarkInstallationSuccessful(index) !=
      IM_EXT_SUCCESS) {
    LOG(ERROR) << "Updater failed to mark the current installation successful";
  }
}

void UpdaterModule::Update() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // If updater_configurator_ is nullptr, the updater is suspended.
  if (updater_configurator_ == nullptr) {
    return;
  }
  const std::vector<std::string> app_ids = {
      updater_configurator_->GetAppGuid()};

  const base::Version manifest_version(GetCurrentEvergreenVersion());
  if (!manifest_version.IsValid()) {
    LOG(ERROR) << "Updater failed to get the current update version.";
    return;
  }

  update_client_->Update(
      app_ids,
      base::BindOnce(
          [](base::Version manifest_version,
             const std::vector<std::string>& ids)
              -> std::vector<base::Optional<update_client::CrxComponent>> {
            update_client::CrxComponent component;
            component.name = "cobalt";
            component.app_id = ids[0];
            component.version = manifest_version;
            component.pk_hash.assign(std::begin(kCobaltPublicKeyHash),
                                     std::end(kCobaltPublicKeyHash));
            component.requires_network_encryption = true;
            component.crx_format_requirement = crx_file::VerifierFormat::CRX3;
            return {component};
          },
          manifest_version),
      false,
      base::BindOnce(
          [](base::OnceClosure closure, update_client::Error error) {
            base::ThreadTaskRunnerHandle::Get()->PostTask(
                FROM_HERE, base::BindOnce(&QuitLoop, std::move(closure)));
          },
          base::Bind(base::DoNothing::Repeatedly())));

  IncrementUpdateCheckCount();

  int kNextUpdateCheckHours = 0;
  if (GetUpdateCheckCount() == 1) {
    // Update check ran once. The next check will be scheduled at a randomized
    // time between 1 and 24 hours.
    kNextUpdateCheckHours = base::RandInt(1, 24);
  } else {
    // Update check ran at least twice. The next check will be scheduled in 24
    // hours.
    kNextUpdateCheckHours = 24;
  }
  updater_thread_->task_runner()->PostDelayedTask(
      FROM_HERE, base::Bind(&UpdaterModule::Update, base::Unretained(this)),
      base::TimeDelta::FromHours(kNextUpdateCheckHours));
}

// The following methods are called by other threads than the updater_thread_.

void UpdaterModule::CompareAndSwapChannelChanged(int old_value, int new_value) {
  auto config = updater_configurator_;
  if (config) config->CompareAndSwapChannelChanged(old_value, new_value);
}

std::string UpdaterModule::GetUpdaterChannel() const {
  LOG(INFO) << "UpdaterModule::GetUpdaterChannel";
  auto config = updater_configurator_;
  if (!config) {
    LOG(ERROR) << "UpdaterModule::GetUpdaterChannel: missing configurator";
    return "";
  }

  std::string channel = config->GetChannel();
  LOG(INFO) << "UpdaterModule::GetUpdaterChannel channel=" << channel;
  return channel;
}

void UpdaterModule::SetUpdaterChannel(const std::string& updater_channel) {
  LOG(INFO) << "UpdaterModule::SetUpdaterChannel updater_channel="
            << updater_channel;
  auto config = updater_configurator_;
  if (config) config->SetChannel(updater_channel);
}

std::string UpdaterModule::GetUpdaterStatus() const {
  LOG(INFO) << "UpdaterModule::GetUpdaterStatus";
  auto config = updater_configurator_;
  if (!config) {
    LOG(ERROR) << "UpdaterModule::GetUpdaterStatus: missing configurator";
    return "";
  }

  std::string updater_status = config->GetUpdaterStatus();
  LOG(INFO) << "UpdaterModule::GetUpdaterStatus updater_status="
            << updater_status;
  return updater_status;
}

void UpdaterModule::RunUpdateCheck() {
  updater_thread_->task_runner()->PostTask(
      FROM_HERE, base::Bind(&UpdaterModule::Update, base::Unretained(this)));
}

void UpdaterModule::ResetInstallations() {
  auto installation_manager =
      static_cast<const CobaltExtensionInstallationManagerApi*>(
          SbSystemGetExtension(kCobaltExtensionInstallationManagerName));
  if (!installation_manager) {
    LOG(ERROR) << "Updater failed to get installation manager extension.";
    return;
  }
  if (installation_manager->Reset() == IM_EXT_ERROR) {
    LOG(ERROR) << "Updater failed to reset installations.";
    return;
  }
  base::FilePath product_data_dir;
  if (!GetProductDirectoryPath(&product_data_dir)) {
    LOG(ERROR) << "Updater failed to get product directory path.";
    return;
  }
  if (!starboard::SbFileDeleteRecursive(product_data_dir.value().c_str(),
                                        true)) {
    LOG(ERROR) << "Updater failed to clean the product directory.";
    return;
  }
}

int UpdaterModule::GetInstallationIndex() const {
  auto installation_manager =
      static_cast<const CobaltExtensionInstallationManagerApi*>(
          SbSystemGetExtension(kCobaltExtensionInstallationManagerName));
  if (!installation_manager) {
    LOG(ERROR) << "Updater failed to get installation manager extension.";
    return -1;
  }
  int index = installation_manager->GetCurrentInstallationIndex();
  if (index == IM_EXT_ERROR) {
    LOG(ERROR) << "Updater failed to get current installation index.";
    return -1;
  }
  return index;
}

void UpdaterModule::SetMinFreeSpaceBytes(uint64_t bytes) {
  LOG(INFO) << "UpdaterModule::SetMinFreeSpaceBytes bytes=" << bytes;
  if (updater_configurator_) {
    updater_configurator_->SetMinFreeSpaceBytes(bytes);
  }
}

// TODO(b/244367569): refactor similar getter and setter methods in this class
// to share common code.
bool UpdaterModule::GetUseCompressedUpdates() const {
  LOG(INFO) << "UpdaterModule::GetUseCompressedUpdates";
  auto config = updater_configurator_;
  if (!config) {
    LOG(ERROR) << "UpdaterModule::GetUseCompressedUpdates: missing "
               << "configurator";
    return false;
  }

  bool use_compressed_updates = config->GetUseCompressedUpdates();
  LOG(INFO) << "UpdaterModule::GetUseCompressedUpdates use_compressed_updates="
            << use_compressed_updates;
  return use_compressed_updates;
}

void UpdaterModule::SetUseCompressedUpdates(bool use_compressed_updates) {
  auto config = updater_configurator_;
  if (!config) {
    LOG(ERROR) << "UpdaterModule::SetUseCompressedUpdates: missing "
               << "configurator";
    return;
  }

  LOG(INFO) << "UpdaterModule::SetUseCompressedUpdates use_compressed_updates="
            << use_compressed_updates;
  config->SetUseCompressedUpdates(use_compressed_updates);
}


}  // namespace updater
}  // namespace cobalt
