// Copyright 2014 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 "components/update_client/update_checker.h"

#include <stddef.h>

#include <algorithm>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "base/threading/thread_checker.h"
#if defined(STARBOARD)
#include "base/threading/thread_id_name_manager.h"
#include "cobalt/extension/free_space.h"
#endif
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#if defined(STARBOARD)
#include "cobalt/updater/utils.h"
#include "components/update_client/cobalt_slot_management.h"
#endif
#include "components/update_client/component.h"
#include "components/update_client/configurator.h"
#include "components/update_client/persisted_data.h"
#include "components/update_client/protocol_definition.h"
#include "components/update_client/protocol_handler.h"
#include "components/update_client/protocol_serializer.h"
#include "components/update_client/request_sender.h"
#include "components/update_client/task_traits.h"
#include "components/update_client/update_client.h"
#include "components/update_client/updater_state.h"
#include "components/update_client/utils.h"
#include "url/gurl.h"

namespace update_client {

namespace {

// Returns a sanitized version of the brand or an empty string otherwise.
std::string SanitizeBrand(const std::string& brand) {
  return IsValidBrand(brand) ? brand : std::string("");
}

// Returns true if at least one item requires network encryption.
bool IsEncryptionRequired(const IdToComponentPtrMap& components) {
  for (const auto& item : components) {
    const auto& component = item.second;
    if (component->crx_component() &&
        component->crx_component()->requires_network_encryption)
      return true;
  }
  return false;
}

// Filters invalid attributes from |installer_attributes|.
using InstallerAttributesFlatMap = base::flat_map<std::string, std::string>;
InstallerAttributesFlatMap SanitizeInstallerAttributes(
    const InstallerAttributes& installer_attributes) {
  InstallerAttributesFlatMap sanitized_attrs;
  for (const auto& attr : installer_attributes) {
    if (IsValidInstallerAttribute(attr))
      sanitized_attrs.insert(attr);
  }
  return sanitized_attrs;
}

class UpdateCheckerImpl : public UpdateChecker {
 public:
  UpdateCheckerImpl(scoped_refptr<Configurator> config,
                    PersistedData* metadata);
  ~UpdateCheckerImpl() override;

  // Overrides for UpdateChecker.
  void CheckForUpdates(
      const std::string& session_id,
      const std::vector<std::string>& ids_checked,
      const IdToComponentPtrMap& components,
      const base::flat_map<std::string, std::string>& additional_attributes,
      bool enabled_component_updates,
      UpdateCheckCallback update_check_callback) override;

#if defined(STARBOARD)
  PersistedData* GetPersistedData() override { return metadata_; }
#endif

 private:
  void ReadUpdaterStateAttributes();
  void CheckForUpdatesHelper(
      const std::string& session_id,
      const IdToComponentPtrMap& components,
      const base::flat_map<std::string, std::string>& additional_attributes,
      bool enabled_component_updates);
#if defined(STARBOARD)
  void Cancel() ;
  virtual bool SkipUpdate(const CobaltExtensionInstallationManagerApi* installation_api);
#endif
  void OnRequestSenderComplete(int error,
                               const std::string& response,
                               int retry_after_sec);
  void UpdateCheckSucceeded(const ProtocolParser::Results& results,
                            int retry_after_sec);
  void UpdateCheckFailed(ErrorCategory error_category,
                         int error,
                         int retry_after_sec);

  base::ThreadChecker thread_checker_;

  const scoped_refptr<Configurator> config_;
  PersistedData* metadata_ = nullptr;
  std::vector<std::string> ids_checked_;
  UpdateCheckCallback update_check_callback_;
  std::unique_ptr<UpdaterState::Attributes> updater_state_attributes_;
  std::unique_ptr<RequestSender> request_sender_;

  DISALLOW_COPY_AND_ASSIGN(UpdateCheckerImpl);
};

UpdateCheckerImpl::UpdateCheckerImpl(scoped_refptr<Configurator> config,
                                     PersistedData* metadata)
    : config_(config), metadata_(metadata) {
#if defined(STARBOARD)
  LOG(INFO) << "UpdateCheckerImpl::UpdateCheckerImpl";
#endif
}

UpdateCheckerImpl::~UpdateCheckerImpl() {
  DCHECK(thread_checker_.CalledOnValidThread());
#if defined(STARBOARD)
  LOG(INFO) << "UpdateCheckerImpl::~UpdateCheckerImpl";
#endif
}

void UpdateCheckerImpl::CheckForUpdates(
    const std::string& session_id,
    const std::vector<std::string>& ids_checked,
    const IdToComponentPtrMap& components,
    const base::flat_map<std::string, std::string>& additional_attributes,
    bool enabled_component_updates,
    UpdateCheckCallback update_check_callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
#if defined(STARBOARD)
  LOG(INFO) << "UpdateCheckerImpl::CheckForUpdates";
#endif

  ids_checked_ = ids_checked;
  update_check_callback_ = std::move(update_check_callback);

  base::PostTaskWithTraitsAndReply(
      FROM_HERE, kTaskTraits,
      base::BindOnce(&UpdateCheckerImpl::ReadUpdaterStateAttributes,
                     base::Unretained(this)),
      base::BindOnce(&UpdateCheckerImpl::CheckForUpdatesHelper,
                     base::Unretained(this), session_id, std::cref(components),
                     additional_attributes, enabled_component_updates));
}

// This function runs on the blocking pool task runner.
void UpdateCheckerImpl::ReadUpdaterStateAttributes() {
#if defined(STARBOARD)
  LOG(INFO) << "UpdateCheckerImpl::ReadUpdaterStateAttributes current_thread="
    << base::ThreadIdNameManager::GetInstance()->GetNameForCurrentThread();
#endif

#if defined(OS_WIN)
  // On Windows, the Chrome and the updater install modes are matched by design.
  updater_state_attributes_ =
      UpdaterState::GetState(!config_->IsPerUserInstall());
#elif defined(OS_MACOSX) && !defined(OS_IOS)
  // MacOS ignores this value in the current implementation but this may change.
  updater_state_attributes_ = UpdaterState::GetState(false);
#else
// Other platforms don't have updaters.
#endif  // OS_WIN
}

void UpdateCheckerImpl::CheckForUpdatesHelper(
    const std::string& session_id,
    const IdToComponentPtrMap& components,
    const base::flat_map<std::string, std::string>& additional_attributes,
    bool enabled_component_updates) {
  DCHECK(thread_checker_.CalledOnValidThread());
#if defined(STARBOARD)
  LOG(INFO) << "UpdateCheckerImpl::CheckForUpdatesHelper";
#endif

  auto urls(config_->UpdateUrl());
  if (IsEncryptionRequired(components))
    RemoveUnsecureUrls(&urls);

  // Components in this update check are either all foreground, or all
  // background since this member is inherited from the component's update
  // context. Pick the state of the first component to use in the update check.
  DCHECK(!components.empty());
  const bool is_foreground = components.at(ids_checked_[0])->is_foreground();
  DCHECK(
      std::all_of(components.cbegin(), components.cend(),
                  [is_foreground](IdToComponentPtrMap::const_reference& elem) {
                    return is_foreground == elem.second->is_foreground();
                  }));

  std::vector<protocol_request::App> apps;
  for (const auto& app_id : ids_checked_) {
    DCHECK_EQ(1u, components.count(app_id));
    const auto& component = components.at(app_id);
    DCHECK_EQ(component->id(), app_id);
    const auto& crx_component = component->crx_component();
    DCHECK(crx_component);

    std::string install_source;
    if (!crx_component->install_source.empty())
      install_source = crx_component->install_source;
    else if (component->is_foreground())
      install_source = "ondemand";

    const bool is_update_disabled =
        crx_component->supports_group_policy_enable_component_updates &&
        !enabled_component_updates;

    base::Version current_version = crx_component->version;
#if defined(STARBOARD)
    // Check if there is an available update already for quick roll-forward
    auto installation_api =
        static_cast<const CobaltExtensionInstallationManagerApi*>(
            SbSystemGetExtension(kCobaltExtensionInstallationManagerName));
    if (!installation_api) {
      LOG(ERROR) << "UpdaterChecker: "
                 << "Failed to get installation manager extension.";
      return;
    }

    if (SkipUpdate(installation_api)) {
      LOG(WARNING) << "UpdaterChecker is skipping";
      UpdateCheckFailed(ErrorCategory::kUpdateCheck,
        static_cast<int>(UpdateCheckError::OUT_OF_SPACE), -1);
      return;
    }

    if (CobaltQuickUpdate(installation_api, current_version)) {
      // The last parameter in UpdateCheckFailed below, which is to be passed to
      // update_check_callback_, indicates a throttling by the update server.
      // Only non-negative values are valid. Negative values are not trusted
      // and are ignored.
      UpdateCheckFailed(ErrorCategory::kUpdateCheck,
                        static_cast<int>(UpdateCheckError::QUICK_ROLL_FORWARD),
                        -1);

      return;
    }

    std::string last_installed_version =
        GetPersistedData()->GetLastInstalledVersion(app_id);
    // If the version of the last installed update package is higher than the
    // version of the running binary, use the former to indicate the current
    // update version in the update check request.
    if (!last_installed_version.empty() &&
        base::Version(last_installed_version).CompareTo(current_version) > 0) {
      current_version = base::Version(last_installed_version);
    }
// If the quick roll forward update slot candidate doesn't exist, continue
// with update check.
#endif
    apps.push_back(MakeProtocolApp(
        app_id, current_version, SanitizeBrand(config_->GetBrand()),
        install_source, crx_component->install_location,
        crx_component->fingerprint,
        SanitizeInstallerAttributes(crx_component->installer_attributes),
        metadata_->GetCohort(app_id), metadata_->GetCohortName(app_id),
        metadata_->GetCohortHint(app_id), crx_component->disabled_reasons,
        MakeProtocolUpdateCheck(is_update_disabled),
        MakeProtocolPing(app_id, metadata_)));
  }
  std::string updater_channel = config_->GetChannel();

  const auto request = MakeProtocolRequest(
      session_id, config_->GetProdId(),
      config_->GetBrowserVersion().GetString(), config_->GetLang(),
      updater_channel, config_->GetOSLongName(),
      config_->GetDownloadPreference(), additional_attributes,
      updater_state_attributes_.get(), std::move(apps));

  request_sender_ = std::make_unique<RequestSender>(config_);
  request_sender_->Send(
      urls,
      BuildUpdateCheckExtraRequestHeaders(config_->GetProdId(),
                                          config_->GetBrowserVersion(),
                                          ids_checked_, is_foreground),
      config_->GetProtocolHandlerFactory()->CreateSerializer()->Serialize(
          request),
      config_->EnabledCupSigning(),
      base::BindOnce(&UpdateCheckerImpl::OnRequestSenderComplete,
                     base::Unretained(this)));
#if defined(STARBOARD)
  // Reset is_channel_changed flag to false if it is true
  config_->CompareAndSwapChannelChanged(1, 0);
#endif
}

#if defined(STARBOARD)
void UpdateCheckerImpl::Cancel() {
  LOG(INFO) << "UpdateCheckerImpl::Cancel";
  if (request_sender_.get()) {
    request_sender_->Cancel();
  }
}

bool UpdateCheckerImpl::SkipUpdate(
  const CobaltExtensionInstallationManagerApi* installation_api) {
  auto free_space_ext = static_cast<const CobaltExtensionFreeSpaceApi*>(
      SbSystemGetExtension(kCobaltExtensionFreeSpaceName));
  if (!installation_api) {
    LOG(WARNING) << "UpdaterChecker::SkipUpdate: missing installation api";
     return false;
  }
  if (!free_space_ext) {
    LOG(WARNING) << "UpdaterChecker::SkipUpdate: No FreeSpace Cobalt extension";
    return false;
  }

  return CobaltSkipUpdate(installation_api, config_->GetMinFreeSpaceBytes(),
     free_space_ext->MeasureFreeSpace(kSbSystemPathStorageDirectory),
     CobaltInstallationCleanupSize(installation_api)) ;
}
#endif

void UpdateCheckerImpl::OnRequestSenderComplete(int error,
                                                const std::string& response,
                                                int retry_after_sec) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (error) {
    VLOG(1) << "RequestSender failed " << error;
    UpdateCheckFailed(ErrorCategory::kUpdateCheck, error, retry_after_sec);
    return;
  }

  auto parser = config_->GetProtocolHandlerFactory()->CreateParser();
  if (!parser->Parse(response)) {
    VLOG(1) << "Parse failed " << parser->errors();
    UpdateCheckFailed(ErrorCategory::kUpdateCheck,
                      static_cast<int>(ProtocolError::PARSE_FAILED),
                      retry_after_sec);
    return;
  }

  DCHECK_EQ(0, error);
  UpdateCheckSucceeded(parser->results(), retry_after_sec);
}

void UpdateCheckerImpl::UpdateCheckSucceeded(
    const ProtocolParser::Results& results,
    int retry_after_sec) {
  DCHECK(thread_checker_.CalledOnValidThread());

  const int daynum = results.daystart_elapsed_days;
  if (daynum != ProtocolParser::kNoDaystart) {
    metadata_->SetDateLastActive(ids_checked_, daynum);
    metadata_->SetDateLastRollCall(ids_checked_, daynum);
  }
  for (const auto& result : results.list) {
    auto entry = result.cohort_attrs.find(ProtocolParser::Result::kCohort);
    if (entry != result.cohort_attrs.end())
      metadata_->SetCohort(result.extension_id, entry->second);
    entry = result.cohort_attrs.find(ProtocolParser::Result::kCohortName);
    if (entry != result.cohort_attrs.end())
      metadata_->SetCohortName(result.extension_id, entry->second);
    entry = result.cohort_attrs.find(ProtocolParser::Result::kCohortHint);
    if (entry != result.cohort_attrs.end())
      metadata_->SetCohortHint(result.extension_id, entry->second);
  }

  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(std::move(update_check_callback_),
                     base::make_optional<ProtocolParser::Results>(results),
                     ErrorCategory::kNone, 0, retry_after_sec));
}

void UpdateCheckerImpl::UpdateCheckFailed(ErrorCategory error_category,
                                          int error,
                                          int retry_after_sec) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_NE(0, error);

  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(std::move(update_check_callback_), base::nullopt,
                     error_category, error, retry_after_sec));
}

}  // namespace

std::unique_ptr<UpdateChecker> UpdateChecker::Create(
    scoped_refptr<Configurator> config,
    PersistedData* persistent) {
  return std::make_unique<UpdateCheckerImpl>(config, persistent);
}

}  // namespace update_client
