// Copyright 2019 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/core/content_capture/content_capture_task.h"

#include <cmath>

#include "base/auto_reset.h"
#include "base/feature_list.h"
#include "cc/trees/layer_tree_host.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/web/web_content_capture_client.h"
#include "third_party/blink/public/web/web_content_holder.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"

namespace blink {

ContentCaptureTask::TaskDelay::TaskDelay(
    const base::TimeDelta& task_short_delay,
    const base::TimeDelta& task_long_delay)
    : task_short_delay_(task_short_delay), task_long_delay_(task_long_delay) {}

base::TimeDelta ContentCaptureTask::TaskDelay::ResetAndGetInitialDelay() {
  delay_exponent_ = 0;
  return task_short_delay_;
}

base::TimeDelta ContentCaptureTask::TaskDelay::GetNextTaskDelay() const {
  return base::TimeDelta::FromMilliseconds(task_short_delay_.InMilliseconds() *
                                           (1 << delay_exponent_));
}

void ContentCaptureTask::TaskDelay::IncreaseDelayExponent() {
  // Increases the delay up to 128s.
  if (delay_exponent_ < 8)
    ++delay_exponent_;
}

ContentCaptureTask::ContentCaptureTask(LocalFrame& local_frame_root,
                                       TaskSession& task_session)
    : local_frame_root_(&local_frame_root),
      task_session_(&task_session),
      delay_task_(
          local_frame_root_->GetTaskRunner(TaskType::kInternalContentCapture),
          this,
          &ContentCaptureTask::Run) {
  base::TimeDelta task_short_delay;
  base::TimeDelta task_long_delay;

  local_frame_root.Client()
      ->GetWebContentCaptureClient()
      ->GetTaskTimingParameters(task_short_delay, task_long_delay);
  task_delay_ = std::make_unique<TaskDelay>(task_short_delay, task_long_delay);

  // The histogram is all about time, just disable it if high resolution isn't
  // supported.
  if (base::TimeTicks::IsHighResolution()) {
    histogram_reporter_ =
        base::MakeRefCounted<ContentCaptureTaskHistogramReporter>();
    task_session_->SetSentNodeCountCallback(
        WTF::BindRepeating(&ContentCaptureTaskHistogramReporter::
                               RecordsSentContentCountPerDocument,
                           histogram_reporter_));
  }
}

ContentCaptureTask::~ContentCaptureTask() = default;

void ContentCaptureTask::Shutdown() {
  DCHECK(local_frame_root_);
  local_frame_root_ = nullptr;
  CancelTask();
}

bool ContentCaptureTask::CaptureContent(Vector<cc::NodeInfo>& data) {
  if (captured_content_for_testing_) {
    data = captured_content_for_testing_.value();
    return true;
  }
  // Because this is called from a different task, the frame may be in any
  // lifecycle step so we need to early-out in many cases.
  if (const auto* root_frame_view = local_frame_root_->View()) {
    if (const auto* cc_layer = root_frame_view->RootCcLayer()) {
      if (auto* layer_tree_host = cc_layer->layer_tree_host()) {
        std::vector<cc::NodeInfo> content;
        if (layer_tree_host->CaptureContent(&content)) {
          for (auto c : content)
            data.push_back(std::move(c));
          return true;
        }
        return false;
      }
    }
  }
  return false;
}

bool ContentCaptureTask::CaptureContent() {
  DCHECK(task_session_);
  Vector<cc::NodeInfo> buffer;
  if (histogram_reporter_)
    histogram_reporter_->OnCaptureContentStarted();
  bool result = CaptureContent(buffer);
  if (!buffer.IsEmpty())
    task_session_->SetCapturedContent(buffer);
  if (histogram_reporter_)
    histogram_reporter_->OnCaptureContentEnded(buffer.size());
  return result;
}

void ContentCaptureTask::SendContent(
    TaskSession::DocumentSession& doc_session) {
  auto* document = doc_session.GetDocument();
  DCHECK(document);
  auto* client = GetWebContentCaptureClient(*document);
  DCHECK(client);

  if (histogram_reporter_)
    histogram_reporter_->OnSendContentStarted();
  WebVector<WebContentHolder> content_batch;
  content_batch.reserve(kBatchSize);
  // Only send changed content after the new content was sent.
  bool sending_changed_content = !doc_session.HasUnsentCapturedContent();
  while (content_batch.size() < kBatchSize) {
    ContentHolder* holder;
    if (sending_changed_content)
      holder = doc_session.GetNextChangedNode();
    else
      holder = doc_session.GetNextUnsentNode();
    if (!holder)
      break;
    content_batch.emplace_back(WebContentHolder(*holder));
  }
  if (!content_batch.empty()) {
    if (sending_changed_content) {
      client->DidUpdateContent(content_batch);
    } else {
      client->DidCaptureContent(content_batch, !doc_session.FirstDataHasSent());
      doc_session.SetFirstDataHasSent();
    }
  }
  if (histogram_reporter_)
    histogram_reporter_->OnSendContentEnded(content_batch.size());
}

WebContentCaptureClient* ContentCaptureTask::GetWebContentCaptureClient(
    const Document& document) {
  if (auto* frame = document.GetFrame())
    return frame->Client()->GetWebContentCaptureClient();
  return nullptr;
}

bool ContentCaptureTask::ProcessSession() {
  DCHECK(task_session_);
  while (auto* document_session =
             task_session_->GetNextUnsentDocumentSession()) {
    if (!ProcessDocumentSession(*document_session))
      return false;
    if (ShouldPause())
      return !task_session_->HasUnsentData();
  }
  return true;
}

bool ContentCaptureTask::ProcessDocumentSession(
    TaskSession::DocumentSession& doc_session) {
  // If no client, we don't need to send it at all.
  auto* content_capture_client =
      GetWebContentCaptureClient(*doc_session.GetDocument());
  if (!content_capture_client) {
    doc_session.Reset();
    return true;
  }

  while (doc_session.HasUnsentCapturedContent() ||
         doc_session.HasUnsentChangedContent()) {
    SendContent(doc_session);
    if (ShouldPause()) {
      return !doc_session.HasUnsentData();
    }
  }
  // Sent the detached nodes.
  if (doc_session.HasUnsentDetachedNodes())
    content_capture_client->DidRemoveContent(doc_session.MoveDetachedNodes());
  DCHECK(!doc_session.HasUnsentData());
  return true;
}

bool ContentCaptureTask::RunInternal() {
  base::AutoReset<TaskState> state(&task_state_, TaskState::kProcessRetryTask);
  // Already shutdown.
  if (!local_frame_root_)
    return true;

  do {
    switch (task_state_) {
      case TaskState::kProcessRetryTask:
        if (task_session_->HasUnsentData()) {
          if (!ProcessSession())
            return false;
        }
        task_state_ = TaskState::kCaptureContent;
        break;
      case TaskState::kCaptureContent:
        if (!has_content_change_)
          return true;
        if (!CaptureContent()) {
          // Don't schedule task again in this case.
          return true;
        }
        has_content_change_ = false;
        if (!task_session_->HasUnsentData())
          return true;

        task_state_ = TaskState::kProcessCurrentSession;
        break;
      case TaskState::kProcessCurrentSession:
        return ProcessSession();
      default:
        return true;
    }
  } while (!ShouldPause());
  return false;
}

void ContentCaptureTask::Run(TimerBase*) {
  TRACE_EVENT0("content_capture", "RunTask");
  task_delay_->IncreaseDelayExponent();
  if (histogram_reporter_)
    histogram_reporter_->OnTaskRun();
  bool completed = RunInternal();
  if (!completed) {
    ScheduleInternal(ScheduleReason::kRetryTask);
  }
  if (histogram_reporter_ &&
      (completed || task_state_ == TaskState::kCaptureContent)) {
    // The current capture session ends if the task indicates it completed or
    // is about to capture the new changes.
    histogram_reporter_->OnAllCapturedContentSent();
  }
}

base::TimeDelta ContentCaptureTask::GetAndAdjustDelay(ScheduleReason reason) {
  bool user_activated_delay_enabled =
      base::FeatureList::IsEnabled(features::kContentCaptureUserActivatedDelay);
  switch (reason) {
    case ScheduleReason::kFirstContentChange:
    case ScheduleReason::kScrolling:
    case ScheduleReason::kRetryTask:
      return user_activated_delay_enabled
                 ? task_delay_->ResetAndGetInitialDelay()
                 : task_delay_->task_short_delay();
    case ScheduleReason::kUserActivatedContentChange:
      return user_activated_delay_enabled
                 ? task_delay_->ResetAndGetInitialDelay()
                 : task_delay_->task_long_delay();
    case ScheduleReason::kNonUserActivatedContentChange:
      return user_activated_delay_enabled ? task_delay_->GetNextTaskDelay()
                                          : task_delay_->task_long_delay();
  }
}

void ContentCaptureTask::ScheduleInternal(ScheduleReason reason) {
  DCHECK(local_frame_root_);
  base::TimeDelta delay = GetAndAdjustDelay(reason);

  // Return if the current task is about to run soon.
  if (delay_task_.IsActive() && delay_task_.NextFireInterval() < delay) {
    return;
  }

  if (delay_task_.IsActive())
    delay_task_.Stop();

  delay_task_.StartOneShot(delay, FROM_HERE);
  TRACE_EVENT_INSTANT1("content_capture", "ScheduleTask",
                       TRACE_EVENT_SCOPE_THREAD, "reason", reason);
  if (histogram_reporter_) {
    histogram_reporter_->OnTaskScheduled(/* record_task_delay = */ reason !=
                                         ScheduleReason::kRetryTask);
  }
}

void ContentCaptureTask::Schedule(ScheduleReason reason) {
  DCHECK(local_frame_root_);
  has_content_change_ = true;
  if (histogram_reporter_)
    histogram_reporter_->OnContentChanged();
  ScheduleInternal(reason);
}

bool ContentCaptureTask::ShouldPause() {
  if (task_stop_for_testing_) {
    return task_state_ == task_stop_for_testing_.value();
  }
  return ThreadScheduler::Current()->ShouldYieldForHighPriorityWork();
}

void ContentCaptureTask::CancelTask() {
  if (delay_task_.IsActive())
    delay_task_.Stop();
}
void ContentCaptureTask::ClearDocumentSessionsForTesting() {
  task_session_->ClearDocumentSessionsForTesting();
}

base::TimeDelta ContentCaptureTask::GetTaskNextFireIntervalForTesting() const {
  return delay_task_.IsActive() ? delay_task_.NextFireInterval()
                                : base::TimeDelta();
}

void ContentCaptureTask::CancelTaskForTesting() {
  CancelTask();
}

void ContentCaptureTask::Trace(Visitor* visitor) const {
  visitor->Trace(local_frame_root_);
  visitor->Trace(task_session_);
  visitor->Trace(delay_task_);
}

}  // namespace blink
