// Copyright 2018 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 "content/browser/background_fetch/storage/get_initialization_data_task.h"

#include "base/barrier_closure.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/browser/background_fetch/storage/image_helpers.h"
#include "content/browser/background_fetch/storage/mark_registration_for_deletion_task.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/common/manifest/manifest.h"
#include "ui/gfx/image/image.h"
#include "url/origin.h"

namespace content {

namespace background_fetch {

namespace {

// Base class with all the common implementation for the SubTasks
// needed in this file.
class InitializationSubTask : public DatabaseTask {
 public:
  // Holds data used by all SubTasks.
  struct SubTaskInit {
    SubTaskInit() = delete;
    ~SubTaskInit() = default;

    // Service Worker Database metadata.
    int64_t service_worker_registration_id;
    std::string unique_id;

    // The results to report.
    BackgroundFetchInitializationData* initialization_data;
  };

  InitializationSubTask(DatabaseTaskHost* host,
                        const SubTaskInit& sub_task_init,
                        base::OnceClosure done_closure)
      : DatabaseTask(host),
        sub_task_init_(sub_task_init),
        done_closure_(std::move(done_closure)) {
    DCHECK(sub_task_init_.initialization_data);
  }

  ~InitializationSubTask() override = default;

 protected:
  void FinishWithError(blink::mojom::BackgroundFetchError error) override {
    if (error != blink::mojom::BackgroundFetchError::NONE)
      sub_task_init_.initialization_data->error = error;
    std::move(done_closure_).Run();
    Finished();  // Destroys |this|.
  }

  SubTaskInit& sub_task_init() { return sub_task_init_; }

 private:
  SubTaskInit sub_task_init_;
  base::OnceClosure done_closure_;

  DISALLOW_COPY_AND_ASSIGN(InitializationSubTask);
};

// Fills the BackgroundFetchInitializationData with the most recent UI title.
class GetUIOptionsTask : public InitializationSubTask {
 public:
  GetUIOptionsTask(DatabaseTaskHost* host,
                   const SubTaskInit& sub_task_init,
                   base::OnceClosure done_closure)
      : InitializationSubTask(host, sub_task_init, std::move(done_closure)),
        weak_factory_(this) {}

  ~GetUIOptionsTask() override = default;

  void Start() override {
    service_worker_context()->GetRegistrationUserData(
        sub_task_init().service_worker_registration_id,
        {UIOptionsKey(sub_task_init().unique_id)},
        base::BindOnce(&GetUIOptionsTask::DidGetUIOptions,
                       weak_factory_.GetWeakPtr()));
  }

 private:
  void DidGetUIOptions(const std::vector<std::string>& data,
                       blink::ServiceWorkerStatusCode status) {
    switch (ToDatabaseStatus(status)) {
      case DatabaseStatus::kFailed:
        FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
        return;
      case DatabaseStatus::kNotFound:
      case DatabaseStatus::kOk:
        break;
    }

    if (data.size() != 1u) {
      FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
      return;
    }

    proto::BackgroundFetchUIOptions ui_options;
    if (!ui_options.ParseFromString(data[0])) {
      FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
      return;
    }

    if (!ui_options.title().empty())
      sub_task_init().initialization_data->ui_title = ui_options.title();

    if (!ui_options.icon().empty()) {
      // Start an icon deserialization SubTask on another thread, then finish.
      DeserializeIcon(std::unique_ptr<std::string>(ui_options.release_icon()),
                      base::BindOnce(&GetUIOptionsTask::DidDeserializeIcon,
                                     weak_factory_.GetWeakPtr()));
    } else {
      FinishWithError(blink::mojom::BackgroundFetchError::NONE);
    }
  }

  void DidDeserializeIcon(SkBitmap icon) {
    sub_task_init().initialization_data->icon = std::move(icon);
    FinishWithError(blink::mojom::BackgroundFetchError::NONE);
  }

  base::WeakPtrFactory<GetUIOptionsTask> weak_factory_;  // Keep as last.
};

// Gets the number of completed fetches, the number of active fetches,
// and deletes inconsistencies in state transitions.
// 1. Get all completed requests.
// 2. Delete matching active requests.
// 3. Get active requests.
// 4. Delete matching pending requests.
class GetRequestsTask : public InitializationSubTask {
 public:
  GetRequestsTask(DatabaseTaskHost* host,
                  const SubTaskInit& sub_task_init,
                  base::OnceClosure done_closure)
      : InitializationSubTask(host, sub_task_init, std::move(done_closure)),
        weak_factory_(this) {}

  ~GetRequestsTask() override = default;

  void Start() override {
    service_worker_context()->GetRegistrationUserDataByKeyPrefix(
        sub_task_init().service_worker_registration_id,
        CompletedRequestKeyPrefix(sub_task_init().unique_id),
        base::BindOnce(&GetRequestsTask::DidGetCompletedRequests,
                       weak_factory_.GetWeakPtr()));
  }

 private:
  void DidGetCompletedRequests(const std::vector<std::string>& data,
                               blink::ServiceWorkerStatusCode status) {
    switch (ToDatabaseStatus(status)) {
      case DatabaseStatus::kFailed:
        FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
        return;
      case DatabaseStatus::kNotFound:
      case DatabaseStatus::kOk:
        break;
    }

    sub_task_init().initialization_data->num_completed_requests = data.size();

    std::vector<std::string> active_requests_to_delete;
    active_requests_to_delete.reserve(data.size());
    for (const std::string& serialized_completed_request : data) {
      proto::BackgroundFetchCompletedRequest completed_request;
      if (!completed_request.ParseFromString(serialized_completed_request) ||
          sub_task_init().unique_id != completed_request.unique_id()) {
        FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
        return;
      }

      active_requests_to_delete.push_back(ActiveRequestKey(
          completed_request.unique_id(), completed_request.request_index()));
    }

    if (active_requests_to_delete.empty()) {
      DidClearActiveRequests(blink::ServiceWorkerStatusCode::kOk);
      return;
    }

    service_worker_context()->ClearRegistrationUserData(
        sub_task_init().service_worker_registration_id,
        std::move(active_requests_to_delete),
        base::BindOnce(&GetRequestsTask::DidClearActiveRequests,
                       weak_factory_.GetWeakPtr()));
  }

  void DidClearActiveRequests(blink::ServiceWorkerStatusCode status) {
    switch (ToDatabaseStatus(status)) {
      case DatabaseStatus::kFailed:
        FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
        return;
      case DatabaseStatus::kNotFound:
      case DatabaseStatus::kOk:
        break;
    }

    service_worker_context()->GetRegistrationUserDataByKeyPrefix(
        sub_task_init().service_worker_registration_id,
        ActiveRequestKeyPrefix(sub_task_init().unique_id),
        base::BindOnce(&GetRequestsTask::DidGetRemainingActiveRequests,
                       weak_factory_.GetWeakPtr()));
  }

  void DidGetRemainingActiveRequests(const std::vector<std::string>& data,
                                     blink::ServiceWorkerStatusCode status) {
    switch (ToDatabaseStatus(status)) {
      case DatabaseStatus::kFailed:
        FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
        return;
      case DatabaseStatus::kNotFound:
      case DatabaseStatus::kOk:
        break;
    }

    std::vector<std::string> pending_requests_to_delete;
    pending_requests_to_delete.reserve(data.size());
    for (const std::string& serialized_active_request : data) {
      proto::BackgroundFetchActiveRequest active_request;
      if (!active_request.ParseFromString(serialized_active_request)) {
        FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
        return;
      }
      DCHECK_EQ(sub_task_init().unique_id, active_request.unique_id());

      auto request_info = base::MakeRefCounted<BackgroundFetchRequestInfo>(
          active_request.request_index(),
          ServiceWorkerUtils::DeserializeFetchRequestFromString(
              active_request.serialized_request()),
          active_request.has_request_body());
      request_info->SetDownloadGuid(active_request.download_guid());

      sub_task_init().initialization_data->active_fetch_requests.push_back(
          std::move(request_info));

      pending_requests_to_delete.push_back(PendingRequestKey(
          active_request.unique_id(), active_request.request_index()));
    }

    if (pending_requests_to_delete.empty()) {
      DidClearPendingRequests(blink::ServiceWorkerStatusCode::kOk);
      return;
    }

    service_worker_context()->ClearRegistrationUserData(
        sub_task_init().service_worker_registration_id,
        std::move(pending_requests_to_delete),
        base::BindOnce(&GetRequestsTask::DidClearPendingRequests,
                       weak_factory_.GetWeakPtr()));
  }

  void DidClearPendingRequests(blink::ServiceWorkerStatusCode status) {
    switch (ToDatabaseStatus(status)) {
      case DatabaseStatus::kFailed:
        FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
        return;
      case DatabaseStatus::kNotFound:
      case DatabaseStatus::kOk:
        break;
    }

    FinishWithError(blink::mojom::BackgroundFetchError::NONE);
  }

  base::WeakPtrFactory<GetRequestsTask> weak_factory_;  // Keep as last.

  DISALLOW_COPY_AND_ASSIGN(GetRequestsTask);
};

// Fills the BackgroundFetchInitializationData with all the relevant information
// stored in the BackgroundFetchMetadata proto.
class FillFromMetadataTask : public InitializationSubTask {
 public:
  FillFromMetadataTask(DatabaseTaskHost* host,
                       const SubTaskInit& sub_task_init,
                       base::OnceClosure done_closure)
      : InitializationSubTask(host, sub_task_init, std::move(done_closure)),
        weak_factory_(this) {}

  ~FillFromMetadataTask() override = default;

  void Start() override {
    service_worker_context()->GetRegistrationUserDataByKeyPrefix(
        sub_task_init().service_worker_registration_id,
        {RegistrationKey(sub_task_init().unique_id)},
        base::BindOnce(&FillFromMetadataTask::DidGetMetadata,
                       weak_factory_.GetWeakPtr()));
  }

 private:
  void DidGetMetadata(const std::vector<std::string>& data,
                      blink::ServiceWorkerStatusCode status) {
    switch (ToDatabaseStatus(status)) {
      case DatabaseStatus::kFailed:
      case DatabaseStatus::kNotFound:
        FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
        return;
      case DatabaseStatus::kOk:
        break;
    }

    if (data.size() != 1u) {
      FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
      return;
    }

    proto::BackgroundFetchMetadata metadata;
    if (!metadata.ParseFromString(data[0])) {
      FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
      return;
    }

    if (sub_task_init().unique_id != metadata.registration().unique_id()) {
      FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
      return;
    }

    // Fill BackgroundFetchRegistrationId.
    sub_task_init().initialization_data->registration_id =
        BackgroundFetchRegistrationId(
            sub_task_init().service_worker_registration_id,
            url::Origin::Create(GURL(metadata.origin())),
            metadata.registration().developer_id(),
            metadata.registration().unique_id());

    // Fill BackgroundFetchRegistration.
    auto& registration = sub_task_init().initialization_data->registration;
    ToBackgroundFetchRegistration(metadata, registration.get());

    // Total number of requests.
    sub_task_init().initialization_data->num_requests = metadata.num_fetches();
    // Fill BackgroundFetchOptions.
    auto& options = sub_task_init().initialization_data->options;
    options->title = metadata.options().title();
    options->download_total = metadata.options().download_total();
    options->icons.reserve(metadata.options().icons_size());
    for (const auto& icon : metadata.options().icons()) {
      blink::Manifest::ImageResource ir;
      ir.src = GURL(icon.src());
      ir.type = base::ASCIIToUTF16(icon.type());

      ir.sizes.reserve(icon.sizes_size());
      for (const auto& size : icon.sizes())
        ir.sizes.emplace_back(size.width(), size.height());

      ir.purpose.reserve(icon.purpose_size());
      for (auto purpose : icon.purpose()) {
        switch (purpose) {
          case proto::BackgroundFetchOptions_ImageResource_Purpose_ANY:
            ir.purpose.push_back(blink::Manifest::ImageResource::Purpose::ANY);
            break;
          case proto::BackgroundFetchOptions_ImageResource_Purpose_BADGE:
            ir.purpose.push_back(
                blink::Manifest::ImageResource::Purpose::BADGE);
            break;
        }
      }
    }

    FinishWithError(blink::mojom::BackgroundFetchError::NONE);
  }

  base::WeakPtrFactory<FillFromMetadataTask> weak_factory_;  // Keep as last.

  DISALLOW_COPY_AND_ASSIGN(FillFromMetadataTask);
};

// Asynchronously calls the SubTasks required to collect all the information for
// the BackgroundFetchInitializationData.
class FillBackgroundFetchInitializationDataTask : public InitializationSubTask {
 public:
  FillBackgroundFetchInitializationDataTask(DatabaseTaskHost* host,
                                            const SubTaskInit& sub_task_init,
                                            base::OnceClosure done_closure)
      : InitializationSubTask(host, sub_task_init, std::move(done_closure)),
        weak_factory_(this) {}

  ~FillBackgroundFetchInitializationDataTask() override = default;

  void Start() override {
    // We need 3 queries to get the initialization data. These are wrapped
    // in a BarrierClosure to avoid querying them serially.
    // 1. Metadata
    // 2. Request statuses and state sanitization
    // 3. UI Options (+ icon deserialization)
    base::RepeatingClosure barrier_closure = base::BarrierClosure(
        3u,
        base::BindOnce(
            [](base::WeakPtr<FillBackgroundFetchInitializationDataTask> task) {
              if (task)
                task->FinishWithError(
                    task->sub_task_init().initialization_data->error);
            },
            weak_factory_.GetWeakPtr()));
    AddSubTask(std::make_unique<FillFromMetadataTask>(this, sub_task_init(),
                                                      barrier_closure));
    AddSubTask(std::make_unique<GetRequestsTask>(this, sub_task_init(),
                                                 barrier_closure));
    AddSubTask(std::make_unique<GetUIOptionsTask>(this, sub_task_init(),
                                                  barrier_closure));
  }

 private:
  base::WeakPtrFactory<FillBackgroundFetchInitializationDataTask>
      weak_factory_;  // Keep as last.

  DISALLOW_COPY_AND_ASSIGN(FillBackgroundFetchInitializationDataTask);
};

}  // namespace

BackgroundFetchInitializationData::BackgroundFetchInitializationData() =
    default;

BackgroundFetchInitializationData::BackgroundFetchInitializationData(
    BackgroundFetchInitializationData&&) = default;

BackgroundFetchInitializationData::~BackgroundFetchInitializationData() =
    default;

GetInitializationDataTask::GetInitializationDataTask(
    DatabaseTaskHost* host,
    GetInitializationDataCallback callback)
    : DatabaseTask(host), callback_(std::move(callback)), weak_factory_(this) {}

GetInitializationDataTask::~GetInitializationDataTask() = default;

void GetInitializationDataTask::Start() {
  service_worker_context()->GetUserDataForAllRegistrationsByKeyPrefix(
      kActiveRegistrationUniqueIdKeyPrefix,
      base::BindOnce(&GetInitializationDataTask::DidGetRegistrations,
                     weak_factory_.GetWeakPtr()));
}

void GetInitializationDataTask::DidGetRegistrations(
    const std::vector<std::pair<int64_t, std::string>>& user_data,
    blink::ServiceWorkerStatusCode status) {
  switch (ToDatabaseStatus(status)) {
    case DatabaseStatus::kFailed:
      FinishWithError(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
      return;
    case DatabaseStatus::kNotFound:
    case DatabaseStatus::kOk:
      break;
  }

  if (user_data.empty()) {
    FinishWithError(blink::mojom::BackgroundFetchError::NONE);
    return;
  }

  base::RepeatingClosure barrier_closure = base::BarrierClosure(
      user_data.size(),
      base::BindOnce(&GetInitializationDataTask::FinishWithError,
                     weak_factory_.GetWeakPtr(),
                     blink::mojom::BackgroundFetchError::NONE));

  for (const auto& ud : user_data) {
    auto insertion_result = initialization_data_map_.emplace(
        ud.second, BackgroundFetchInitializationData());
    DCHECK(insertion_result.second);  // Check unique_id is in fact unique.

    AddSubTask(std::make_unique<FillBackgroundFetchInitializationDataTask>(
        this,
        InitializationSubTask::SubTaskInit{
            ud.first, ud.second,
            &insertion_result.first->second /* initialization_data */},
        barrier_closure));
  }
}
void GetInitializationDataTask::FinishWithError(
    blink::mojom::BackgroundFetchError error) {
  std::vector<BackgroundFetchInitializationData> results;
  results.reserve(initialization_data_map_.size());

  for (auto& data : initialization_data_map_) {
    if (data.second.error == blink::mojom::BackgroundFetchError::NONE) {
      // If we successfully extracted all the data, move it to the
      // initialization vector to be handed over to create a controller.
      results.emplace_back(std::move(data.second));
    } else if (!data.second.registration_id.developer_id().empty()) {
      // There was an error in getting the initialization data
      // (e.g. corrupt data, SWDB error). If the Developer ID of the fetch
      // is available, mark the registration for deletion.
      // Note that the Developer ID isn't available if the metadata extraction
      // failed.
      // TODO(crbug.com/865388): Getting the Developer ID should be possible
      // since it is part of the key for when we got the Unique ID.
      AddDatabaseTask(std::make_unique<MarkRegistrationForDeletionTask>(
          data_manager(), data.second.registration_id,
          /* check_for_failure= */ false, base::DoNothing()));
    }

    if (data.second.error ==
        blink::mojom::BackgroundFetchError::STORAGE_ERROR) {
      // The subtasks only access the Service Worker storage, so if there is
      // a storage error, that would be the cause.
      SetStorageError(BackgroundFetchStorageError::kServiceWorkerStorageError);
    }
  }

  ReportStorageError();

  std::move(callback_).Run(error, std::move(results));
  Finished();  // Destroys |this|.
}

std::string GetInitializationDataTask::HistogramName() const {
  return "GetInitializationDataTask";
}

}  // namespace background_fetch

}  // namespace content
