// Copyright 2019 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/scheduler/browser_task_queues.h"

#include <iterator>

#include "base/check.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/sequence_manager/sequence_manager.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "content/browser/scheduler/browser_task_priority.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"

namespace content {
namespace {

using BrowserTaskPriority = ::content::internal::BrowserTaskPriority;
using QueueName = ::perfetto::protos::pbzero::SequenceManagerTask::QueueName;
using InsertFencePosition =
    ::base::sequence_manager::TaskQueue::InsertFencePosition;
using QueueEnabledVoter = base::sequence_manager::TaskQueue::QueueEnabledVoter;

QueueName GetControlTaskQueueName(BrowserThread::ID thread_id) {
  switch (thread_id) {
    case BrowserThread::UI:
      return QueueName::UI_CONTROL_TQ;
    case BrowserThread::IO:
      return QueueName::IO_CONTROL_TQ;
    case BrowserThread::ID_COUNT:
      break;
  }
  NOTREACHED();
}

QueueName GetRunAllPendingTaskQueueName(BrowserThread::ID thread_id) {
  switch (thread_id) {
    case BrowserThread::UI:
      return QueueName::UI_RUN_ALL_PENDING_TQ;
    case BrowserThread::IO:
      return QueueName::IO_RUN_ALL_PENDING_TQ;
    case BrowserThread::ID_COUNT:
      break;
  }
  NOTREACHED();
}

QueueName GetUITaskQueueName(BrowserTaskQueues::QueueType queue_type) {
  switch (queue_type) {
    case BrowserTaskQueues::QueueType::kBestEffort:
      return QueueName::UI_BEST_EFFORT_TQ;
    case BrowserTaskQueues::QueueType::kDefault:
      return QueueName::UI_DEFAULT_TQ;
    case BrowserTaskQueues::QueueType::kUserBlocking:
      return QueueName::UI_USER_BLOCKING_TQ;
    case BrowserTaskQueues::QueueType::kUserVisible:
      return QueueName::UI_USER_VISIBLE_TQ;
    case BrowserTaskQueues::QueueType::kUserInput:
      return QueueName::UI_USER_INPUT_TQ;
    case BrowserTaskQueues::QueueType::kNavigationNetworkResponse:
      return QueueName::UI_NAVIGATION_NETWORK_RESPONSE_TQ;
    case BrowserTaskQueues::QueueType::kServiceWorkerStorageControlResponse:
      return QueueName::UI_SERVICE_WORKER_STORAGE_CONTROL_RESPONSE_TQ;
    case BrowserTaskQueues::QueueType::kBeforeUnloadBrowserResponse:
      return QueueName::UI_BEFORE_UNLOAD_BROWSER_RESPONSE_TQ;
    case BrowserTaskQueues::QueueType::kStartup:
      return QueueName::UI_STARTUP_TQ;
  }
}

QueueName GetIOTaskQueueName(BrowserTaskQueues::QueueType queue_type) {
  switch (queue_type) {
    case BrowserTaskQueues::QueueType::kBestEffort:
      return QueueName::IO_BEST_EFFORT_TQ;
    case BrowserTaskQueues::QueueType::kDefault:
      return QueueName::IO_DEFAULT_TQ;
    case BrowserTaskQueues::QueueType::kUserBlocking:
      return QueueName::IO_USER_BLOCKING_TQ;
    case BrowserTaskQueues::QueueType::kUserVisible:
      return QueueName::IO_USER_VISIBLE_TQ;
    case BrowserTaskQueues::QueueType::kUserInput:
      return QueueName::IO_USER_INPUT_TQ;
    case BrowserTaskQueues::QueueType::kNavigationNetworkResponse:
      return QueueName::IO_NAVIGATION_NETWORK_RESPONSE_TQ;
    case BrowserTaskQueues::QueueType::kServiceWorkerStorageControlResponse:
      return QueueName::IO_SERVICE_WORKER_STORAGE_CONTROL_RESPONSE_TQ;
    case BrowserTaskQueues::QueueType::kBeforeUnloadBrowserResponse:
      return QueueName::IO_BEFORE_UNLOAD_BROWSER_RESPONSE_TQ;
    case BrowserTaskQueues::QueueType::kStartup:
      return QueueName::IO_STARTUP_TQ;
  }
}

QueueName GetTaskQueueName(BrowserThread::ID thread_id,
                           BrowserTaskQueues::QueueType queue_type) {
  switch (thread_id) {
    case BrowserThread::UI:
      return GetUITaskQueueName(queue_type);
    case BrowserThread::IO:
      return GetIOTaskQueueName(queue_type);
    case BrowserThread::ID_COUNT:
      break;
  }
  NOTREACHED();
}

}  // namespace

BrowserTaskQueues::QueueData::QueueData() = default;
BrowserTaskQueues::QueueData::~QueueData() = default;
BrowserTaskQueues::QueueData::QueueData(BrowserTaskQueues::QueueData&& other) =
    default;

BrowserTaskQueues::Handle::~Handle() = default;

BrowserTaskQueues::Handle::Handle(BrowserTaskQueues* outer)
    : outer_(outer),
      control_task_runner_(outer_->control_queue_->task_runner()),
      default_task_runner_(outer_->GetDefaultTaskQueue()->task_runner()),
      browser_task_runners_(outer_->CreateBrowserTaskRunners()) {}

void BrowserTaskQueues::Handle::OnStartupComplete() {
  control_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&BrowserTaskQueues::OnStartupComplete,
                                base::Unretained(outer_)));
}

void BrowserTaskQueues::Handle::EnableAllExceptBestEffortQueues() {
  control_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&BrowserTaskQueues::EnableAllExceptBestEffortQueues,
                     base::Unretained(outer_)));
}

void BrowserTaskQueues::Handle::EnableTaskQueue(QueueType type) {
  control_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&BrowserTaskQueues::EnableTaskQueue,
                                base::Unretained(outer_), type));
}

void BrowserTaskQueues::Handle::ScheduleRunAllPendingTasksForTesting(
    base::OnceClosure on_pending_task_ran) {
  control_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(
          &BrowserTaskQueues::StartRunAllPendingTasksForTesting,
          base::Unretained(outer_),
          base::ScopedClosureRunner(std::move(on_pending_task_ran))));
}

BrowserTaskQueues::BrowserTaskQueues(
    BrowserThread::ID thread_id,
    base::sequence_manager::SequenceManager* sequence_manager) {
  for (size_t i = 0; i < queue_data_.size(); ++i) {
    queue_data_[i].task_queue = sequence_manager->CreateTaskQueue(
        base::sequence_manager::TaskQueue::Spec(
            GetTaskQueueName(thread_id, static_cast<QueueType>(i))));
    queue_data_[i].voter = queue_data_[i].task_queue->CreateQueueEnabledVoter();
    queue_data_[i].voter->SetVoteToEnable(false);
  }

  GetBrowserTaskQueue(QueueType::kUserVisible)
      ->SetQueuePriority(BrowserTaskPriority::kLowPriority);

  // Best effort queue
  GetBrowserTaskQueue(QueueType::kBestEffort)
      ->SetQueuePriority(BrowserTaskPriority::kBestEffortPriority);

  // User Input queue
  GetBrowserTaskQueue(QueueType::kUserInput)
      ->SetQueuePriority(BrowserTaskPriority::kHighestPriority);

  GetBrowserTaskQueue(QueueType::kNavigationNetworkResponse)
      ->SetQueuePriority(BrowserTaskPriority::kHighPriority);

  GetBrowserTaskQueue(QueueType::kServiceWorkerStorageControlResponse)
      ->SetQueuePriority(BrowserTaskPriority::kHighestPriority);

  GetBrowserTaskQueue(QueueType::kBeforeUnloadBrowserResponse)
      ->SetQueuePriority(BrowserTaskPriority::kHighPriority);

  // Control queue
  control_queue_ =
      sequence_manager->CreateTaskQueue(base::sequence_manager::TaskQueue::Spec(
          GetControlTaskQueueName(thread_id)));
  control_queue_->SetQueuePriority(BrowserTaskPriority::kControlPriority);

  // Run all pending queue
  run_all_pending_tasks_queue_ =
      sequence_manager->CreateTaskQueue(base::sequence_manager::TaskQueue::Spec(
          GetRunAllPendingTaskQueueName(thread_id)));
  run_all_pending_tasks_queue_->SetQueuePriority(
      BrowserTaskPriority::kBestEffortPriority);

  handle_ = base::AdoptRef(new Handle(this));
}

BrowserTaskQueues::~BrowserTaskQueues() {
  for (auto& queue : queue_data_) {
    queue.task_queue.reset();
  }
  control_queue_.reset();
  run_all_pending_tasks_queue_.reset();
  handle_->OnTaskQueuesDestroyed();
}

std::array<scoped_refptr<base::SingleThreadTaskRunner>,
           BrowserTaskQueues::kNumQueueTypes>
BrowserTaskQueues::CreateBrowserTaskRunners() const {
  std::array<scoped_refptr<base::SingleThreadTaskRunner>, kNumQueueTypes>
      task_runners;
  for (size_t i = 0; i < queue_data_.size(); ++i) {
    task_runners[i] = queue_data_[i].task_queue->task_runner();
  }
  return task_runners;
}

void BrowserTaskQueues::OnStartupComplete() {
  // Enable all queues
  for (const auto& queue : queue_data_) {
    queue.voter->SetVoteToEnable(true);
  }

  // Update ServiceWorker task queue priority.
  DCHECK_EQ(
      static_cast<BrowserTaskPriority>(
          GetBrowserTaskQueue(QueueType::kServiceWorkerStorageControlResponse)
              ->GetQueuePriority()),
      BrowserTaskPriority::kHighestPriority);
  GetBrowserTaskQueue(QueueType::kServiceWorkerStorageControlResponse)
      ->SetQueuePriority(BrowserTaskPriority::kHighPriority);
}

void BrowserTaskQueues::EnableTaskQueue(QueueType type) {
  queue_data_[static_cast<size_t>(type)].voter->SetVoteToEnable(true);
}

void BrowserTaskQueues::EnableAllExceptBestEffortQueues() {
  for (size_t i = 0; i < queue_data_.size(); ++i) {
    if (i != static_cast<size_t>(QueueType::kBestEffort)) {
      queue_data_[i].voter->SetVoteToEnable(true);
    }
  }
}

// To run all pending tasks we do the following. We insert a fence in all queues
// and post a task to the |run_all_pending_queue_| which has the lowest priority
// possible. That makes sure that all tasks up to the fences will have run
// before this posted task runs. Note that among tasks with the same priority
// ties are broken by using the enqueue order, so all prior best effort tasks
// will have run before this one does. This task will then remove all the fences
// and call the user provided callback to signal that all pending tasks have
// run. This method is "reentrant" as in we can call it multiple times as the
// fences will just be moved back, but we need to make sure that only the last
// call removes the fences, for that we keep track of "nesting" with
// |run_all_pending_nesting_level_|
void BrowserTaskQueues::StartRunAllPendingTasksForTesting(
    base::ScopedClosureRunner on_pending_task_ran) {
  ++run_all_pending_nesting_level_;
  for (const auto& queue : queue_data_) {
    queue.task_queue->InsertFence(InsertFencePosition::kNow);
  }
  run_all_pending_tasks_queue_->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&BrowserTaskQueues::EndRunAllPendingTasksForTesting,
                     base::Unretained(this), std::move(on_pending_task_ran)));
}

void BrowserTaskQueues::EndRunAllPendingTasksForTesting(
    base::ScopedClosureRunner on_pending_task_ran) {
  --run_all_pending_nesting_level_;
  if (run_all_pending_nesting_level_ == 0) {
    for (const auto& queue : queue_data_) {
      queue.task_queue->RemoveFence();
    }
  }
}

void BrowserTaskQueues::SetOnTaskCompletedHandler(
    base::sequence_manager::TaskQueue::OnTaskCompletedHandler handler) {
  for (auto& queue : queue_data_) {
    queue.task_queue->SetOnTaskCompletedHandler(handler);
  }
}

void BrowserTaskQueues::AddTaskObserver(base::TaskObserver* task_observer) {
  for (const auto& queue : queue_data_) {
    queue.task_queue->AddTaskObserver(task_observer);
  }
}

}  // namespace content
