// Copyright 2017 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 "third_party/blink/renderer/modules/service_worker/service_worker_event_queue.h"

#include "base/bind.h"
#include "base/containers/contains.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom-blink.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"

namespace blink {

// static
constexpr base::TimeDelta ServiceWorkerEventQueue::kEventTimeout;
constexpr base::TimeDelta ServiceWorkerEventQueue::kUpdateInterval;

ServiceWorkerEventQueue::StayAwakeToken::StayAwakeToken(
    base::WeakPtr<ServiceWorkerEventQueue> event_queue)
    : event_queue_(std::move(event_queue)) {
  DCHECK(event_queue_);
  event_queue_->ResetIdleTimeout();
  event_queue_->num_of_stay_awake_tokens_++;
}

ServiceWorkerEventQueue::StayAwakeToken::~StayAwakeToken() {
  // If |event_queue_| has already been destroyed, it means the worker thread
  // has already been killed.
  if (!event_queue_)
    return;
  DCHECK_GT(event_queue_->num_of_stay_awake_tokens_, 0);
  event_queue_->num_of_stay_awake_tokens_--;

  if (!event_queue_->HasInflightEvent())
    event_queue_->OnNoInflightEvent();
}

ServiceWorkerEventQueue::ServiceWorkerEventQueue(
    BeforeStartEventCallback before_start_event_callback,
    base::RepeatingClosure idle_callback,
    scoped_refptr<base::SequencedTaskRunner> task_runner)
    : ServiceWorkerEventQueue(std::move(before_start_event_callback),
                              std::move(idle_callback),
                              std::move(task_runner),
                              base::DefaultTickClock::GetInstance()) {}

ServiceWorkerEventQueue::ServiceWorkerEventQueue(
    BeforeStartEventCallback before_start_event_callback,
    base::RepeatingClosure idle_callback,
    scoped_refptr<base::SequencedTaskRunner> task_runner,
    const base::TickClock* tick_clock)
    : task_runner_(std::move(task_runner)),
      before_start_event_callback_(std::move(before_start_event_callback)),
      idle_callback_(std::move(idle_callback)),
      tick_clock_(tick_clock) {}

ServiceWorkerEventQueue::~ServiceWorkerEventQueue() {
  // Abort all callbacks.
  for (auto& event : all_events_) {
    std::move(event.value->abort_callback)
        .Run(blink::mojom::ServiceWorkerEventStatus::ABORTED);
  }
}

void ServiceWorkerEventQueue::Start() {
  DCHECK(!timer_.IsRunning());
  if (!HasInflightEvent() && !HasScheduledIdleCallback()) {
    // If no event happens until Start(), the idle callback should be scheduled.
    OnNoInflightEvent();
  }
  timer_.Start(FROM_HERE, kUpdateInterval,
               WTF::BindRepeating(&ServiceWorkerEventQueue::UpdateStatus,
                                  WTF::Unretained(this)));
}

void ServiceWorkerEventQueue::EnqueueNormal(
    int event_id,
    StartCallback start_callback,
    AbortCallback abort_callback,
    base::Optional<base::TimeDelta> custom_timeout) {
  EnqueueEvent(std::make_unique<Event>(
      event_id, Event::Type::Normal, std::move(start_callback),
      std::move(abort_callback), std::move(custom_timeout)));
}

void ServiceWorkerEventQueue::EnqueuePending(
    int event_id,
    StartCallback start_callback,
    AbortCallback abort_callback,
    base::Optional<base::TimeDelta> custom_timeout) {
  EnqueueEvent(std::make_unique<Event>(
      event_id, Event::Type::Pending, std::move(start_callback),
      std::move(abort_callback), std::move(custom_timeout)));
}

void ServiceWorkerEventQueue::EnqueueOffline(
    int event_id,
    StartCallback start_callback,
    AbortCallback abort_callback,
    base::Optional<base::TimeDelta> custom_timeout) {
  EnqueueEvent(std::make_unique<ServiceWorkerEventQueue::Event>(
      event_id, ServiceWorkerEventQueue::Event::Type::Offline,
      std::move(start_callback), std::move(abort_callback),
      std::move(custom_timeout)));
}

bool ServiceWorkerEventQueue::CanStartEvent(const Event& event) const {
  if (running_event_type_ == RunningEventType::kNone) {
    DCHECK(!HasInflightEvent());
    return true;
  }
  if (event.type == Event::Type::Offline)
    return running_event_type_ == RunningEventType::kOffline;
  return running_event_type_ == RunningEventType::kOnline;
}

std::map<int, std::unique_ptr<ServiceWorkerEventQueue::Event>>&
ServiceWorkerEventQueue::GetActiveEventQueue() {
  if (running_event_type_ == RunningEventType::kNone) {
    // Either online events or offline events can be started when inflight
    // events don't exist. If online events exist in the queue, prioritize
    // online events.
    return queued_online_events_.empty() ? queued_offline_events_
                                         : queued_online_events_;
  }
  if (running_event_type_ == RunningEventType::kOffline)
    return queued_offline_events_;
  return queued_online_events_;
}

void ServiceWorkerEventQueue::EnqueueEvent(std::unique_ptr<Event> event) {
  DCHECK(event->type != Event::Type::Pending || did_idle_timeout());
  DCHECK(!HasEvent(event->event_id));
  DCHECK(!HasEventInQueue(event->event_id));

  bool can_start_processing_events =
      !processing_events_ && event->type != Event::Type::Pending;

  // Start counting the timer when an event is enqueued.
  all_events_.insert(
      event->event_id,
      std::make_unique<EventInfo>(
          tick_clock_->NowTicks() +
              event->custom_timeout.value_or(kEventTimeout),
          WTF::Bind(std::move(event->abort_callback), event->event_id)));

  auto& queue = event->type == Event::Type::Offline ? queued_offline_events_
                                                    : queued_online_events_;
  queue.emplace(event->event_id, std::move(event));

  if (!can_start_processing_events)
    return;

  ResetIdleTimeout();
  ProcessEvents();
}

void ServiceWorkerEventQueue::ProcessEvents() {
  DCHECK(!processing_events_);
  processing_events_ = true;
  auto& queue = GetActiveEventQueue();
  while (!queue.empty() && CanStartEvent(*queue.begin()->second)) {
    int event_id = queue.begin()->first;
    std::unique_ptr<Event> event = std::move(queue.begin()->second);
    queue.erase(queue.begin());
    StartEvent(event_id, std::move(event));
  }
  processing_events_ = false;

  // We have to check HasInflightEvent() and may trigger
  // OnNoInflightEvent() here because StartEvent() can call EndEvent()
  // synchronously, and EndEvent() never triggers OnNoInflightEvent()
  // while ProcessEvents() is running.
  if (!HasInflightEvent())
    OnNoInflightEvent();
}

void ServiceWorkerEventQueue::StartEvent(int event_id,
                                         std::unique_ptr<Event> event) {
  DCHECK(HasEvent(event_id));
  running_event_type_ = event->type == Event::Type::Offline
                            ? RunningEventType::kOffline
                            : RunningEventType::kOnline;
  if (before_start_event_callback_)
    before_start_event_callback_.Run(event->type == Event::Type::Offline);
  std::move(event->start_callback).Run(event_id);
}

void ServiceWorkerEventQueue::EndEvent(int event_id) {
  DCHECK(HasEvent(event_id));
  all_events_.erase(event_id);
  // Check |processing_events_| here because EndEvent() can be called
  // synchronously in StartEvent(). We don't want to trigger
  // OnNoInflightEvent() while ProcessEvents() is running.
  if (!processing_events_ && !HasInflightEvent())
    OnNoInflightEvent();
}

bool ServiceWorkerEventQueue::HasEvent(int event_id) const {
  return all_events_.find(event_id) != all_events_.end();
}

bool ServiceWorkerEventQueue::HasEventInQueue(int event_id) const {
  return (base::Contains(queued_online_events_, event_id) ||
          base::Contains(queued_offline_events_, event_id));
}

std::unique_ptr<ServiceWorkerEventQueue::StayAwakeToken>
ServiceWorkerEventQueue::CreateStayAwakeToken() {
  return std::make_unique<ServiceWorkerEventQueue::StayAwakeToken>(
      weak_factory_.GetWeakPtr());
}

void ServiceWorkerEventQueue::SetIdleDelay(base::TimeDelta idle_delay) {
  idle_delay_ = idle_delay;

  if (HasInflightEvent())
    return;

  if (did_idle_timeout()) {
    // The idle callback has already been called. It should not be called again
    // until this worker becomes active.
    return;
  }

  // There should be a scheduled idle callback because this is now in the idle
  // delay. The idle callback will be rescheduled based on the new idle delay.
  DCHECK(HasScheduledIdleCallback());
  idle_callback_handle_.Cancel();

  // Calculate the updated time of when the |idle_callback_| should be invoked.
  DCHECK(!last_no_inflight_event_.is_null());
  auto new_idle_callback_time = last_no_inflight_event_ + idle_delay;
  base::TimeDelta delta_until_idle =
      new_idle_callback_time - tick_clock_->NowTicks();

  if (delta_until_idle <= base::TimeDelta::FromSeconds(0)) {
    // The new idle delay is shorter than the previous idle delay, and the idle
    // time has been already passed. Let's run the idle callback immediately.
    TriggerIdleCallback();
    return;
  }

  // Let's schedule the idle callback in |delta_until_idle|.
  ScheduleIdleCallback(delta_until_idle);
}

void ServiceWorkerEventQueue::UpdateStatus() {
  base::TimeTicks now = tick_clock_->NowTicks();

  // Construct a new map because WTF::HashMap doesn't support deleting elements
  // while iterating.
  HashMap<int /* event_id */, std::unique_ptr<EventInfo>> new_all_events;

  bool should_idle_delay_to_be_zero = false;

  // Time out all events exceeding `kEventTimeout`.
  for (auto& it : all_events_) {
    // Check if the event has timed out.
    int event_id = it.key;
    std::unique_ptr<EventInfo>& event_info = it.value;
    if (event_info->expiration_time > now) {
      new_all_events.insert(event_id, std::move(event_info));
      continue;
    }

    // The event may still be in one of the queues when it timed out. Try to
    // remove the event from both.
    queued_online_events_.erase(event_id);
    queued_offline_events_.erase(event_id);

    // Run the abort callback.
    std::move(event_info->abort_callback)
        .Run(blink::mojom::ServiceWorkerEventStatus::TIMEOUT);

    should_idle_delay_to_be_zero = true;
  }
  all_events_.swap(new_all_events);

  // Set idle delay to zero if needed.
  if (should_idle_delay_to_be_zero) {
    // Inflight events might be timed out and there might be no inflight event
    // at this point.
    if (!HasInflightEvent()) {
      OnNoInflightEvent();
    }
    // Shut down the worker as soon as possible since the worker may have gone
    // into bad state.
    SetIdleDelay(base::TimeDelta::FromSeconds(0));
  }
}

void ServiceWorkerEventQueue::ScheduleIdleCallback(base::TimeDelta delay) {
  DCHECK(!HasInflightEvent());
  DCHECK(!HasScheduledIdleCallback());

  // WTF::Unretained() is safe because the task runner will be destroyed
  // before |this| is destroyed at ServiceWorkerGlobalScope::Dispose().
  idle_callback_handle_ = PostDelayedCancellableTask(
      *task_runner_, FROM_HERE,
      WTF::Bind(&ServiceWorkerEventQueue::TriggerIdleCallback,
                WTF::Unretained(this)),
      delay);
}

void ServiceWorkerEventQueue::TriggerIdleCallback() {
  DCHECK(!HasInflightEvent());
  DCHECK(!HasScheduledIdleCallback());
  DCHECK(!did_idle_timeout_);

  did_idle_timeout_ = true;
  idle_callback_.Run();
}

void ServiceWorkerEventQueue::OnNoInflightEvent() {
  DCHECK(!HasInflightEvent());
  running_event_type_ = RunningEventType::kNone;
  // There might be events in the queue because offline (or non-offline) events
  // can be enqueued during running non-offline (or offline) events.
  auto& queue = GetActiveEventQueue();
  if (!queue.empty()) {
    ProcessEvents();
    return;
  }
  last_no_inflight_event_ = tick_clock_->NowTicks();
  ScheduleIdleCallback(idle_delay_);
}

bool ServiceWorkerEventQueue::HasInflightEvent() const {
  size_t num_queued_events =
      queued_online_events_.size() + queued_offline_events_.size();
  DCHECK_LE(num_queued_events, all_events_.size());
  return all_events_.size() - num_queued_events > 0 ||
         num_of_stay_awake_tokens_ > 0;
}

void ServiceWorkerEventQueue::ResetIdleTimeout() {
  last_no_inflight_event_ = base::TimeTicks();
  idle_callback_handle_.Cancel();
  did_idle_timeout_ = false;
}

bool ServiceWorkerEventQueue::HasScheduledIdleCallback() const {
  return idle_callback_handle_.IsActive();
}

int ServiceWorkerEventQueue::NextEventId() {
  CHECK_LT(next_event_id_, std::numeric_limits<int>::max());
  return next_event_id_++;
}

ServiceWorkerEventQueue::Event::Event(
    int event_id,
    ServiceWorkerEventQueue::Event::Type type,
    StartCallback start_callback,
    AbortCallback abort_callback,
    base::Optional<base::TimeDelta> custom_timeout)
    : event_id(event_id),
      type(type),
      start_callback(std::move(start_callback)),
      abort_callback(std::move(abort_callback)),
      custom_timeout(custom_timeout) {}

ServiceWorkerEventQueue::Event::~Event() = default;

ServiceWorkerEventQueue::EventInfo::EventInfo(
    base::TimeTicks expiration_time,
    base::OnceCallback<void(blink::mojom::ServiceWorkerEventStatus)>
        abort_callback)
    : expiration_time(expiration_time),
      abort_callback(std::move(abort_callback)) {}

ServiceWorkerEventQueue::EventInfo::~EventInfo() = default;

}  // namespace blink
