// Copyright 2017 The Chromium Authors
// 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/background_fetch_scheduler.h"

#include "base/containers/cxx20_erase.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/string_number_conversions.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/background_fetch_delegate_proxy.h"
#include "content/browser/background_fetch/background_fetch_job_controller.h"
#include "content/browser/background_fetch/background_fetch_registration_notifier.h"
#include "content/browser/background_fetch/background_fetch_registration_service_impl.h"
#include "content/browser/devtools/devtools_background_services_context_impl.h"
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/common/content_features.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"

namespace content {

namespace {

// The maximum number of active registrations that can be processed
// concurrently. The active registrations are from distinct origins.
constexpr char kMaxActiveRegistrations[] = "max_active_registrations";
constexpr int kMaxActiveRegistrationsDefaultValue = 2;

// The maximum number of downloads the Download Service can process at the same
// time.
// TODO(crbug.com/919864): Figure out how to keep this in sync with the
// Download Service value.
constexpr char kMaxRunningDownloads[] = "max_running_downloads";
constexpr int kMaxRunningDownloadsDefaultValue = 2;

}  // namespace

using blink::mojom::BackgroundFetchError;
using blink::mojom::BackgroundFetchFailureReason;

// The major stages/events a Background Fetch instance goes through via the
// BackgroundFetchScheduler.
enum class BackgroundFetchScheduler::Event {
  // The Background Fetch was successfully registered.
  kFetchRegistered,
  // The Background Fetch registration was loaded on start-up.
  kFetchResumedOnStartup,
  // The scheduler marked the registration as active.
  kFetchScheduled,
  // A request within the registration is being fetched.
  kRequestStarted,
  // A request within the registration had been fetched.
  kRequestCompleted,
};

BackgroundFetchScheduler::BackgroundFetchScheduler(
    BackgroundFetchContext* background_fetch_context,
    BackgroundFetchDataManager* data_manager,
    BackgroundFetchRegistrationNotifier* registration_notifier,
    BackgroundFetchDelegateProxy* delegate_proxy,
    DevToolsBackgroundServicesContextImpl& devtools_context,
    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
    : data_manager_(data_manager),
      registration_notifier_(registration_notifier),
      delegate_proxy_(delegate_proxy),
      devtools_context_(&devtools_context),
      event_dispatcher_(background_fetch_context,
                        std::move(service_worker_context),
                        devtools_context) {
  DCHECK(delegate_proxy_);
  delegate_proxy_->SetClickEventDispatcher(
      base::BindRepeating(&BackgroundFetchScheduler::DispatchClickEvent,
                          weak_ptr_factory_.GetWeakPtr()));

  max_active_registrations_ = base::GetFieldTrialParamByFeatureAsInt(
      features::kBackgroundFetch, kMaxActiveRegistrations,
      kMaxActiveRegistrationsDefaultValue);
  max_running_downloads_ = base::GetFieldTrialParamByFeatureAsInt(
      features::kBackgroundFetch, kMaxRunningDownloads,
      kMaxRunningDownloadsDefaultValue);
}

BackgroundFetchScheduler::~BackgroundFetchScheduler() = default;

BackgroundFetchScheduler::RegistrationData::RegistrationData(
    const BackgroundFetchRegistrationId& registration_id,
    blink::mojom::BackgroundFetchRegistrationDataPtr registration)
    : registration_id(registration_id), registration(std::move(registration)) {}

BackgroundFetchScheduler::RegistrationData::~RegistrationData() = default;

bool BackgroundFetchScheduler::ScheduleDownload() {
  DCHECK_LT(num_running_downloads_, max_running_downloads_);

  // 1. Try to activate a registration from a different storage key.
  if (num_active_registrations_ < max_active_registrations_ &&
      !controller_ids_.empty()) {
    // Try to find a pending registration with a different storage key.
    for (const auto& controller_id : controller_ids_) {
      // Make sure the storage key is not already active.
      bool is_new_storage_key = true;
      for (auto* controller : active_controllers_) {
        if (controller->registration_id().storage_key() ==
            controller_id.storage_key()) {
          is_new_storage_key = false;
          break;
        }
      }

      if (is_new_storage_key) {
        // Start new registration, and move to the front of the queue.
        auto* controller = job_controllers_[controller_id.unique_id()].get();
        active_controllers_.push_front(controller);
        ++num_active_registrations_;

        LogBackgroundFetchEventForDevTools(Event::kFetchScheduled,
                                           controller_id,
                                           /* request_info= */ nullptr);

        base::Erase(controller_ids_, controller_id);
        break;
      }
    }
  }

  // 2. Try to start a request within the LRU registration.
  for (auto it = active_controllers_.begin(); it != active_controllers_.end();
       ++it) {
    auto* controller = *it;
    if (!controller->HasMoreRequests())
      continue;

    // Activate a request within |controller| and move it to the end of the
    // queue.
    ++num_running_downloads_;
    controller->PopNextRequest(
        base::BindOnce(&BackgroundFetchScheduler::DidStartRequest,
                       weak_ptr_factory_.GetWeakPtr()),
        base::BindOnce(&BackgroundFetchScheduler::DidCompleteRequest,
                       weak_ptr_factory_.GetWeakPtr()));

    active_controllers_.erase(it);
    active_controllers_.push_back(controller);
    return true;
  }
  return false;
}

void BackgroundFetchScheduler::Abort(
    const BackgroundFetchRegistrationId& registration_id,
    BackgroundFetchFailureReason failure_reason,
    blink::mojom::BackgroundFetchRegistrationService::AbortCallback callback) {
  DCHECK_EQ(failure_reason,
            BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER);

  base::Erase(controller_ids_, registration_id);

  auto it = job_controllers_.find(registration_id.unique_id());
  if (it == job_controllers_.end()) {
    std::move(callback).Run(BackgroundFetchError::INVALID_ID);
    return;
  }

  it->second->Abort(failure_reason, std::move(callback));
}

void BackgroundFetchScheduler::DidStartRequest(
    const BackgroundFetchRegistrationId& registration_id,
    const BackgroundFetchRequestInfo* request_info) {
  LogBackgroundFetchEventForDevTools(Event::kRequestStarted, registration_id,
                                     request_info);
}

void BackgroundFetchScheduler::DidCompleteRequest(
    const BackgroundFetchRegistrationId& registration_id,
    scoped_refptr<BackgroundFetchRequestInfo> request_info) {
  LogBackgroundFetchEventForDevTools(Event::kRequestCompleted, registration_id,
                                     request_info.get());

  auto* controller = GetActiveController(registration_id);
  if (controller)
    controller->MarkRequestAsComplete(std::move(request_info));

  --num_running_downloads_;
  if (num_running_downloads_ < max_running_downloads_)
    ScheduleDownload();
}

void BackgroundFetchScheduler::FinishJob(
    const BackgroundFetchRegistrationId& registration_id,
    BackgroundFetchFailureReason failure_reason,
    base::OnceCallback<void(BackgroundFetchError)> callback) {
  auto* active_controller = GetActiveController(registration_id);
  if (active_controller) {
    base::EraseIf(active_controllers_, [&registration_id](auto* controller) {
      return controller->registration_id() == registration_id;
    });
  }

  data_manager_->MarkRegistrationForDeletion(
      registration_id,
      /* check_for_failure= */ failure_reason ==
          BackgroundFetchFailureReason::NONE,
      base::BindOnce(&BackgroundFetchScheduler::DidMarkForDeletion,
                     weak_ptr_factory_.GetWeakPtr(), registration_id,
                     /* job_started= */ active_controller != nullptr,
                     std::move(callback)));

  auto it = job_controllers_.find(registration_id.unique_id());
  if (it != job_controllers_.end()) {
    completed_fetches_[it->first] = std::make_unique<RegistrationData>(
        registration_id, it->second->NewRegistrationData());

    // Reset scheduler params.
    num_running_downloads_ -= it->second->pending_downloads();
    --num_active_registrations_;

    // Destroying the controller will stop all in progress tasks.
    job_controllers_.erase(it);
  }

  if (num_running_downloads_ < max_running_downloads_)
    ScheduleDownload();
}

void BackgroundFetchScheduler::DidMarkForDeletion(
    const BackgroundFetchRegistrationId& registration_id,
    bool job_started,
    base::OnceCallback<void(BackgroundFetchError)> callback,
    BackgroundFetchError error,
    BackgroundFetchFailureReason failure_reason) {
  DCHECK(callback);
  std::move(callback).Run(error);

  // It's normal to get INVALID_ID errors here - it means the registration was
  // already inactive (marked for deletion). This happens when an abort (from
  // developer or from user) races with the download completing/failing, or even
  // when two aborts race.
  if (error != BackgroundFetchError::NONE)
    return;

  auto it = completed_fetches_.find(registration_id.unique_id());
  DCHECK(it != completed_fetches_.end());

  blink::mojom::BackgroundFetchRegistrationDataPtr& registration_data =
      it->second->registration;
  // Include any other failure reasons the marking for deletion may have found.
  if (registration_data->failure_reason == BackgroundFetchFailureReason::NONE)
    registration_data->failure_reason = failure_reason;

  registration_data->result =
      registration_data->failure_reason == BackgroundFetchFailureReason::NONE
          ? blink::mojom::BackgroundFetchResult::SUCCESS
          : blink::mojom::BackgroundFetchResult::FAILURE;

  registration_notifier_->Notify(registration_id.unique_id(),
                                 *registration_data);

  event_dispatcher_.DispatchBackgroundFetchCompletionEvent(
      registration_id, registration_data.Clone(),
      base::BindOnce(&BackgroundFetchScheduler::CleanupRegistration,
                     weak_ptr_factory_.GetWeakPtr(), registration_id));

  if (!job_started ||
      registration_data->failure_reason ==
          BackgroundFetchFailureReason::CANCELLED_FROM_UI ||
      registration_data->failure_reason ==
          BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER) {
    // No need to keep the controller around since there won't be dispatch
    // events.
    completed_fetches_.erase(it);
  } else {
    // The registration is now safe to delete.
    it->second->processing_completed = true;
  }
}

void BackgroundFetchScheduler::CleanupRegistration(
    const BackgroundFetchRegistrationId& registration_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  // Indicate to the renderer that the records for this fetch are no longer
  // available.
  registration_notifier_->NotifyRecordsUnavailable(registration_id.unique_id());

  // Delete the data associated with this fetch. Cache storage will keep the
  // downloaded data around so long as there are references to it, and delete
  // it once there is none. We don't need to do that accounting.
  data_manager_->DeleteRegistration(registration_id, base::DoNothing());

  // Notify other systems that this registration is complete.
  delegate_proxy_->MarkJobComplete(registration_id.unique_id());
}

void BackgroundFetchScheduler::DispatchClickEvent(
    const std::string& unique_id) {
  // Case 1: The active fetch received a click event.
  auto* active_controller = GetActiveController(unique_id);

  if (active_controller) {
    event_dispatcher_.DispatchBackgroundFetchClickEvent(
        active_controller->registration_id(),
        active_controller->NewRegistrationData(), base::DoNothing());
    return;
  }

  // Case 2: A completed fetch received a click event.
  auto it = completed_fetches_.find(unique_id);
  if (it == completed_fetches_.end())
    return;

  event_dispatcher_.DispatchBackgroundFetchClickEvent(
      it->second->registration_id, it->second->registration.Clone(),
      base::DoNothing());

  if (it->second->processing_completed)
    completed_fetches_.erase(unique_id);
}

std::unique_ptr<BackgroundFetchJobController>
BackgroundFetchScheduler::CreateInitializedController(
    const BackgroundFetchRegistrationId& registration_id,
    const blink::mojom::BackgroundFetchRegistrationData& registration_data,
    blink::mojom::BackgroundFetchOptionsPtr options,
    const SkBitmap& icon,
    int num_completed_requests,
    int num_requests,
    std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
        active_fetch_requests,
    bool start_paused,
    absl::optional<net::IsolationInfo> isolation_info) {
  // TODO(rayankans): Only create a controller when the fetch starts.
  auto controller = std::make_unique<BackgroundFetchJobController>(
      data_manager_, delegate_proxy_, registration_id, std::move(options), icon,
      registration_data.downloaded, registration_data.uploaded,
      registration_data.upload_total,
      // Safe because JobControllers are destroyed before RegistrationNotifier.
      base::BindRepeating(&BackgroundFetchRegistrationNotifier::Notify,
                          base::Unretained(registration_notifier_)),
      base::BindOnce(&BackgroundFetchScheduler::FinishJob,
                     weak_ptr_factory_.GetWeakPtr()));

  controller->InitializeRequestStatus(num_completed_requests, num_requests,
                                      std::move(active_fetch_requests),
                                      start_paused, std::move(isolation_info));

  return controller;
}

void BackgroundFetchScheduler::OnRegistrationCreated(
    const BackgroundFetchRegistrationId& registration_id,
    const blink::mojom::BackgroundFetchRegistrationData& registration_data,
    blink::mojom::BackgroundFetchOptionsPtr options,
    const SkBitmap& icon,
    int num_requests,
    bool start_paused,
    net::IsolationInfo isolation_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  LogBackgroundFetchEventForDevTools(
      Event::kFetchRegistered, registration_id,
      /* request_info= */ nullptr,
      {{"Total Requests", base::NumberToString(num_requests)},
       {"Start Paused", start_paused ? "Yes" : "No"}});

  auto controller = CreateInitializedController(
      registration_id, registration_data, std::move(options), icon,
      /* completed_requests= */ 0, num_requests,
      /* active_fetch_requests= */ {}, start_paused, std::move(isolation_info));

  DCHECK_EQ(job_controllers_.count(registration_id.unique_id()), 0u);
  job_controllers_[registration_id.unique_id()] = std::move(controller);
  controller_ids_.push_back(registration_id);

  // Schedule as much as possible.
  while (num_running_downloads_ < max_running_downloads_) {
    if (!ScheduleDownload())
      return;
  }
}

void BackgroundFetchScheduler::OnRegistrationLoadedAtStartup(
    const BackgroundFetchRegistrationId& registration_id,
    const blink::mojom::BackgroundFetchRegistrationData& registration_data,
    blink::mojom::BackgroundFetchOptionsPtr options,
    const SkBitmap& icon,
    int num_completed_requests,
    int num_requests,
    std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
        active_fetch_requests,
    absl::optional<net::IsolationInfo> isolation_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  LogBackgroundFetchEventForDevTools(
      Event::kFetchResumedOnStartup, registration_id,
      /* request_info= */ nullptr,
      {{"Completed Requests", base::NumberToString(num_completed_requests)},
       {"Active Requests",
        base::NumberToString(active_fetch_requests.size())}});

  auto controller = CreateInitializedController(
      registration_id, registration_data, std::move(options), icon,
      num_completed_requests, num_requests, active_fetch_requests,
      /* start_paused= */ false, std::move(isolation_info));

  auto* controller_ptr = controller.get();
  active_controllers_.push_back(controller_ptr);
  job_controllers_[registration_id.unique_id()] = std::move(controller);

  ++num_active_registrations_;
  num_running_downloads_ += active_fetch_requests.size();

  if (active_fetch_requests.empty()) {
    DCHECK_LT(num_completed_requests, num_requests);
    // Start processing the next request.
    ++num_running_downloads_;
    controller_ptr->PopNextRequest(
        base::BindOnce(&BackgroundFetchScheduler::DidStartRequest,
                       weak_ptr_factory_.GetWeakPtr()),
        base::BindOnce(&BackgroundFetchScheduler::DidCompleteRequest,
                       weak_ptr_factory_.GetWeakPtr()));
    return;
  }

  for (auto& request_info : active_fetch_requests) {
    controller_ptr->StartRequest(
        std::move(request_info),
        base::BindOnce(&BackgroundFetchScheduler::DidCompleteRequest,
                       weak_ptr_factory_.GetWeakPtr()));
  }
}

void BackgroundFetchScheduler::OnRequestCompleted(
    const std::string& unique_id,
    blink::mojom::FetchAPIRequestPtr request,
    blink::mojom::FetchAPIResponsePtr response) {
  registration_notifier_->NotifyRequestCompleted(unique_id, std::move(request),
                                                 std::move(response));
}

void BackgroundFetchScheduler::AbortFetches(
    int64_t service_worker_registration_id) {
  // Abandon all active associated with this service worker.
  // BackgroundFetchJobController::Abort() will eventually lead to deletion of
  // the controller from job_controllers, so the IDs need to be copied over.
  std::vector<BackgroundFetchJobController*> to_abort;
  for (const auto& controller : job_controllers_) {
    if (service_worker_registration_id !=
            blink::mojom::kInvalidServiceWorkerRegistrationId &&
        service_worker_registration_id !=
            controller.second->registration_id()
                .service_worker_registration_id()) {
      continue;
    }
    to_abort.push_back(controller.second.get());
  }

  for (auto* controller : to_abort) {
    // Erase it from |controller_ids_| first to avoid rescheduling.
    base::Erase(controller_ids_, controller->registration_id());
    controller->Abort(BackgroundFetchFailureReason::SERVICE_WORKER_UNAVAILABLE,
                      base::DoNothing());
  }
}

void BackgroundFetchScheduler::OnRegistrationQueried(
    const BackgroundFetchRegistrationId& registration_id,
    blink::mojom::BackgroundFetchRegistrationData* registration_data) {
  DCHECK(registration_data);

  auto* controller = GetActiveController(registration_id.unique_id());
  if (!controller)
    return;

  // The data manager only has the number of bytes from completed downloads, so
  // augment this with the number of downloaded/uploaded bytes from in-progress
  // jobs.
  registration_data->downloaded += controller->GetInProgressDownloadedBytes();
  registration_data->uploaded += controller->GetInProgressUploadedBytes();
}

void BackgroundFetchScheduler::OnServiceWorkerDatabaseCorrupted(
    int64_t service_worker_registration_id) {
  AbortFetches(service_worker_registration_id);
}

void BackgroundFetchScheduler::OnRegistrationDeleted(
    int64_t registration_id,
    const GURL& pattern,
    const blink::StorageKey& key) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  AbortFetches(registration_id);
}

void BackgroundFetchScheduler::OnStorageWiped() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  AbortFetches(blink::mojom::kInvalidServiceWorkerRegistrationId);
}

BackgroundFetchJobController* BackgroundFetchScheduler::GetActiveController(
    const BackgroundFetchRegistrationId& registration_id) {
  for (auto* controller : active_controllers_) {
    if (controller->registration_id() == registration_id)
      return controller;
  }
  return nullptr;
}

BackgroundFetchJobController* BackgroundFetchScheduler::GetActiveController(
    const std::string& unique_id) {
  // |unique_id| is used for all BackgroundFetchRegistrationId comparisons, so
  // this creates a |unique_id| wrapper with default values for other
  // parameters.
  BackgroundFetchRegistrationId registration_id(
      /* service_worker_registration_id= */ 0,
      /* storage_key= */ blink::StorageKey(),
      /* developer_id= */ "", unique_id);
  return GetActiveController(registration_id);
}

void BackgroundFetchScheduler::LogBackgroundFetchEventForDevTools(
    Event event,
    const BackgroundFetchRegistrationId& registration_id,
    const BackgroundFetchRequestInfo* request_info,
    std::map<std::string, std::string> metadata) {
  CHECK(devtools_context_);
  if (!devtools_context_->IsRecording(
          DevToolsBackgroundService::kBackgroundFetch)) {
    return;
  }

  std::string event_name;

  // Fill with the appropriate event description in |event_name|, and append
  // any additional data to |metadata|.
  switch (event) {
    case Event::kFetchRegistered:
      event_name = "Background Fetch registered";
      break;
    case Event::kFetchResumedOnStartup:
      event_name = "Background Fetch resuming after browser restart";
      break;
    case Event::kFetchScheduled:
      event_name = "Background Fetch started";
      break;
    case Event::kRequestStarted:
      event_name = "Request processing started";
      DCHECK(request_info);
      break;
    case Event::kRequestCompleted:
      event_name = "Request processing completed";
      DCHECK(request_info);
      metadata["Response Status"] =
          base::NumberToString(request_info->GetResponseCode());
      metadata["Response Size (bytes)"] =
          base::NumberToString(request_info->GetResponseSize());
      break;
  }

  DCHECK(!event_name.empty());

  // Include common request metadata.
  if (request_info) {
    metadata["URL"] = request_info->fetch_request()->url.spec();
    metadata["Request Index"] =
        base::NumberToString(request_info->request_index());
    if (request_info->request_body_size())
      metadata["Upload Size (bytes)"] =
          base::NumberToString(request_info->request_body_size());
  }

  devtools_context_->LogBackgroundServiceEvent(
      registration_id.service_worker_registration_id(),
      registration_id.storage_key(),
      DevToolsBackgroundService::kBackgroundFetch, std::move(event_name),
      /* instance_id= */ registration_id.developer_id(), metadata);
}

void BackgroundFetchScheduler::Shutdown() {
  event_dispatcher_.Shutdown();
  devtools_context_ = nullptr;
}

}  // namespace content
