// Copyright 2012 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/renderer_host/clipboard_host_impl.h"

#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/file_system/browser_file_system_helper.h"
#include "content/browser/file_system_access/file_system_access_manager_impl.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/renderer_host/data_transfer_util.h"
#include "content/browser/renderer_host/render_frame_host_delegate.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_client.h"
#include "content/public/common/drop_data.h"
#include "ipc/ipc_message.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "skia/ext/skia_utils_base.h"
#include "third_party/blink/public/mojom/clipboard/clipboard.mojom.h"
#include "third_party/blink/public/mojom/drag/drag.mojom-forward.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/base/clipboard/clipboard_format_type.h"
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/base/clipboard/file_info.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/data_transfer_policy/data_transfer_policy_controller.h"
#include "url/gurl.h"

namespace content {

namespace {
bool IsRendererPasteAllowed(RenderFrameHost& render_frame_host) {
  ContentBrowserClient* browser_client = GetContentClient()->browser();
  return browser_client->IsClipboardPasteAllowed(&render_frame_host);
}
}  // namespace

// 5 mins is based on the timeout in BinaryUploadService. This scanning timeout
// of 5 mins means no paste will be held back longer before being allowed or
// blocked, so matching this timeout with the threshold for a paste being too
// old ensures scans that:
//  - Scans that timeout can be retried without waiting
//  - Scans that succeed will apply their verdicts without the risk that their
//    associated IsPasteContentAllowedRequest is already too old.
const base::TimeDelta ClipboardHostImpl::kIsPasteContentAllowedRequestTooOld =
    base::Minutes(5);

ClipboardHostImpl::IsPasteContentAllowedRequest::
    IsPasteContentAllowedRequest() = default;
ClipboardHostImpl::IsPasteContentAllowedRequest::
    ~IsPasteContentAllowedRequest() = default;

bool ClipboardHostImpl::IsPasteContentAllowedRequest::AddCallback(
    IsClipboardPasteContentAllowedCallback callback) {
  // If this request has already completed, invoke the callback immediately
  // and return.
  if (allowed_.has_value()) {
    std::move(callback).Run(allowed_.value());
    return false;
  }

  callbacks_.push_back(std::move(callback));

  // If this is the first callback registered tell the caller to start the scan.
  return callbacks_.size() == 1;
}

void ClipboardHostImpl::IsPasteContentAllowedRequest::Complete(
    ClipboardPasteContentAllowed allowed) {
  allowed_ = allowed;
  InvokeCallbacks();
}

bool ClipboardHostImpl::IsPasteContentAllowedRequest::IsObsolete(
    base::Time now) {
  // If the request is old and no longer has any registered callbacks it is
  // obsolete.
  return (now - time_) > kIsPasteContentAllowedRequestTooOld &&
         callbacks_.empty();
}

void ClipboardHostImpl::IsPasteContentAllowedRequest::InvokeCallbacks() {
  DCHECK(allowed_);

  auto callbacks = std::move(callbacks_);
  for (auto& callback : callbacks) {
    if (!callback.is_null())
      std::move(callback).Run(allowed_.value());
  }
}

ClipboardHostImpl::ClipboardHostImpl(
    RenderFrameHost& render_frame_host,
    mojo::PendingReceiver<blink::mojom::ClipboardHost> receiver)
    : DocumentService(render_frame_host, std::move(receiver)) {
  clipboard_writer_ = std::make_unique<ui::ScopedClipboardWriter>(
      ui::ClipboardBuffer::kCopyPaste,
      render_frame_host.GetBrowserContext()->IsOffTheRecord()
          ? nullptr
          : std::make_unique<ui::DataTransferEndpoint>(
                render_frame_host.GetMainFrame()->GetLastCommittedURL()));
}

void ClipboardHostImpl::Create(
    RenderFrameHost* render_frame_host,
    mojo::PendingReceiver<blink::mojom::ClipboardHost> receiver) {
  CHECK(render_frame_host);
  // The object is bound to the lifetime of |render_frame_host| and the mojo
  // connection. See DocumentService for details.
  new ClipboardHostImpl(*render_frame_host, std::move(receiver));
}

ClipboardHostImpl::~ClipboardHostImpl() {
  clipboard_writer_->Reset();
}

void ClipboardHostImpl::GetSequenceNumber(ui::ClipboardBuffer clipboard_buffer,
                                          GetSequenceNumberCallback callback) {
  std::move(callback).Run(
      ui::Clipboard::GetForCurrentThread()->GetSequenceNumber(
          clipboard_buffer));
}

void ClipboardHostImpl::ReadAvailableTypes(
    ui::ClipboardBuffer clipboard_buffer,
    ReadAvailableTypesCallback callback) {
  std::vector<std::u16string> types;
  auto* clipboard = ui::Clipboard::GetForCurrentThread();
  auto data_endpoint = CreateDataEndpoint();

  // ReadAvailableTypes() returns 'text/uri-list' if either files are provided,
  // or if it was set as a custom web type. If it is set because files are
  // available, do not include other types such as text/plain which contain the
  // full path on some platforms (http://crbug.com/1214108). But do not exclude
  // other types when it is set as a custom web type (http://crbug.com/1241671).
  if (clipboard->IsFormatAvailable(ui::ClipboardFormatType::FilenamesType(),
                                   clipboard_buffer, data_endpoint.get())) {
    types = {base::UTF8ToUTF16(ui::kMimeTypeURIList)};
  } else {
    clipboard->ReadAvailableTypes(clipboard_buffer, data_endpoint.get(),
                                  &types);
  }
  std::move(callback).Run(types);
}

void ClipboardHostImpl::IsFormatAvailable(blink::mojom::ClipboardFormat format,
                                          ui::ClipboardBuffer clipboard_buffer,
                                          IsFormatAvailableCallback callback) {
  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
  bool result = false;
  auto data_endpoint = CreateDataEndpoint();
  switch (format) {
    case blink::mojom::ClipboardFormat::kPlaintext:
      result =
          clipboard->IsFormatAvailable(ui::ClipboardFormatType::PlainTextType(),
                                       clipboard_buffer, data_endpoint.get());
#if BUILDFLAG(IS_WIN)
      result |= clipboard->IsFormatAvailable(
          ui::ClipboardFormatType::PlainTextAType(), clipboard_buffer,
          data_endpoint.get());
#endif
      break;
    case blink::mojom::ClipboardFormat::kHtml:
      result =
          clipboard->IsFormatAvailable(ui::ClipboardFormatType::HtmlType(),
                                       clipboard_buffer, data_endpoint.get());
      break;
    case blink::mojom::ClipboardFormat::kSmartPaste:
      result = clipboard->IsFormatAvailable(
          ui::ClipboardFormatType::WebKitSmartPasteType(), clipboard_buffer,
          data_endpoint.get());
      break;
    case blink::mojom::ClipboardFormat::kBookmark:
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
      result =
          clipboard->IsFormatAvailable(ui::ClipboardFormatType::UrlType(),
                                       clipboard_buffer, data_endpoint.get());
#else
      result = false;
#endif
      break;
  }
  std::move(callback).Run(result);
}

void ClipboardHostImpl::ReadText(ui::ClipboardBuffer clipboard_buffer,
                                 ReadTextCallback callback) {
  if (!IsRendererPasteAllowed(render_frame_host())) {
    std::move(callback).Run(std::u16string());
    return;
  }
  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
  std::u16string result;
  auto data_dst = CreateDataEndpoint();
  if (clipboard->IsFormatAvailable(ui::ClipboardFormatType::PlainTextType(),
                                   clipboard_buffer, data_dst.get())) {
    clipboard->ReadText(clipboard_buffer, data_dst.get(), &result);
  } else {
#if BUILDFLAG(IS_WIN)
    if (clipboard->IsFormatAvailable(ui::ClipboardFormatType::PlainTextAType(),
                                     clipboard_buffer, data_dst.get())) {
      std::string ascii;
      clipboard->ReadAsciiText(clipboard_buffer, data_dst.get(), &ascii);
      result = base::ASCIIToUTF16(ascii);
    }
#endif
  }

  std::string data = base::UTF16ToUTF8(result);
  PasteIfPolicyAllowed(clipboard_buffer,
                       ui::ClipboardFormatType::PlainTextType(),
                       std::move(data),
                       base::BindOnce(
                           [](std::u16string result, ReadTextCallback callback,
                              ClipboardPasteContentAllowed allowed) {
                             if (!allowed)
                               result.clear();
                             std::move(callback).Run(result);
                           },
                           std::move(result), std::move(callback)));
}

void ClipboardHostImpl::ReadHtml(ui::ClipboardBuffer clipboard_buffer,
                                 ReadHtmlCallback callback) {
  if (!IsRendererPasteAllowed(render_frame_host())) {
    std::move(callback).Run(std::u16string(), GURL(), 0, 0);
    return;
  }
  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
  std::u16string markup;
  std::string src_url_str;
  uint32_t fragment_start = 0;
  uint32_t fragment_end = 0;
  auto data_dst = CreateDataEndpoint();
  clipboard->ReadHTML(clipboard_buffer, data_dst.get(), &markup, &src_url_str,
                      &fragment_start, &fragment_end);

  std::string data = base::UTF16ToUTF8(markup);
  PasteIfPolicyAllowed(
      clipboard_buffer, ui::ClipboardFormatType::HtmlType(), std::move(data),
      base::BindOnce(
          [](std::u16string markup, std::string src_url_str,
             uint32_t fragment_start, uint32_t fragment_end,
             ReadHtmlCallback callback, ClipboardPasteContentAllowed allowed) {
            if (!allowed)
              markup.clear();
            std::move(callback).Run(std::move(markup), GURL(src_url_str),
                                    fragment_start, fragment_end);
          },
          std::move(markup), std::move(src_url_str), fragment_start,
          fragment_end, std::move(callback)));
}

void ClipboardHostImpl::ReadSvg(ui::ClipboardBuffer clipboard_buffer,
                                ReadSvgCallback callback) {
  if (!IsRendererPasteAllowed(render_frame_host())) {
    std::move(callback).Run(std::u16string());
    return;
  }
  std::u16string markup;
  ui::Clipboard::GetForCurrentThread()->ReadSvg(clipboard_buffer,
                                                /*data_dst=*/nullptr, &markup);

  std::string data = base::UTF16ToUTF8(markup);
  PasteIfPolicyAllowed(clipboard_buffer, ui::ClipboardFormatType::SvgType(),
                       std::move(data),
                       base::BindOnce(
                           [](std::u16string markup, ReadSvgCallback callback,
                              ClipboardPasteContentAllowed allowed) {
                             if (!allowed)
                               markup.clear();
                             std::move(callback).Run(std::move(markup));
                           },
                           std::move(markup), std::move(callback)));
}

void ClipboardHostImpl::ReadRtf(ui::ClipboardBuffer clipboard_buffer,
                                ReadRtfCallback callback) {
  if (!IsRendererPasteAllowed(render_frame_host())) {
    std::move(callback).Run(std::string());
    return;
  }
  std::string result;
  auto data_dst = CreateDataEndpoint();
  ui::Clipboard::GetForCurrentThread()->ReadRTF(clipboard_buffer,
                                                data_dst.get(), &result);

  std::string data = result;
  PasteIfPolicyAllowed(clipboard_buffer, ui::ClipboardFormatType::RtfType(),
                       std::move(data),
                       base::BindOnce(
                           [](std::string result, ReadRtfCallback callback,
                              ClipboardPasteContentAllowed allowed) {
                             if (!allowed)
                               result.clear();
                             std::move(callback).Run(result);
                           },
                           std::move(result), std::move(callback)));
}

void ClipboardHostImpl::ReadPng(ui::ClipboardBuffer clipboard_buffer,
                                ReadPngCallback callback) {
  if (!IsRendererPasteAllowed(render_frame_host())) {
    std::move(callback).Run(mojo_base::BigBuffer());
    return;
  }
  auto data_dst = CreateDataEndpoint();
  ui::Clipboard::GetForCurrentThread()->ReadPng(
      clipboard_buffer, data_dst.get(),
      base::BindOnce(&ClipboardHostImpl::OnReadPng,
                     weak_ptr_factory_.GetWeakPtr(), clipboard_buffer,
                     std::move(callback)));
}

void ClipboardHostImpl::OnReadPng(ui::ClipboardBuffer clipboard_buffer,
                                  ReadPngCallback callback,
                                  const std::vector<uint8_t>& data) {
  std::string string_data(data.begin(), data.end());
  PasteIfPolicyAllowed(
      clipboard_buffer, ui::ClipboardFormatType::PngType(),
      std::move(string_data),
      base::BindOnce(
          [](std::vector<uint8_t> data, ReadPngCallback callback,
             ClipboardPasteContentAllowed allowed) {
            if (!allowed) {
              std::move(callback).Run(mojo_base::BigBuffer());
              return;
            }
            std::move(callback).Run(mojo_base::BigBuffer(data));
          },
          std::move(data), std::move(callback)));
}

void ClipboardHostImpl::ReadFiles(ui::ClipboardBuffer clipboard_buffer,
                                  ReadFilesCallback callback) {
  blink::mojom::ClipboardFilesPtr result = blink::mojom::ClipboardFiles::New();
  if (!IsRendererPasteAllowed(render_frame_host())) {
    std::move(callback).Run(std::move(result));
    return;
  }

  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
  std::vector<ui::FileInfo> filenames;
  auto data_dst = CreateDataEndpoint();
  clipboard->ReadFilenames(clipboard_buffer, data_dst.get(), &filenames);
  std::string data = ui::FileInfosToURIList(filenames);

  // This code matches the drag-and-drop DataTransfer code in
  // RenderWidgetHostImpl::DragTargetDrop().

  // Call PrepareDataTransferFilenamesForChildProcess() to register files so
  // they can be accessed by the renderer.
  RenderProcessHost* process = render_frame_host().GetProcess();
  result->file_system_id = PrepareDataTransferFilenamesForChildProcess(
      filenames, ChildProcessSecurityPolicyImpl::GetInstance(),
      process->GetID(), process->GetStoragePartition()->GetFileSystemContext());

  // Convert to DataTransferFiles which creates the access token for each file.
  StoragePartitionImpl* storage_partition = static_cast<StoragePartitionImpl*>(
      render_frame_host().GetProcess()->GetStoragePartition());
  std::vector<blink::mojom::DataTransferFilePtr> files =
      FileInfosToDataTransferFiles(
          filenames, storage_partition->GetFileSystemAccessManager(),
          process->GetID());
  std::move(files.begin(), files.end(), std::back_inserter(result->files));

  PerformPasteIfContentAllowed(
      clipboard->GetSequenceNumber(clipboard_buffer),
      ui::ClipboardFormatType::FilenamesType(), std::move(data),
      base::BindOnce(
          [](blink::mojom::ClipboardFilesPtr result, ReadFilesCallback callback,
             ClipboardPasteContentAllowed allowed) {
            if (!allowed) {
              result->files.clear();
              result->file_system_id->clear();
            }
            std::move(callback).Run(std::move(result));
          },
          std::move(result), std::move(callback)));
}

void ClipboardHostImpl::ReadCustomData(ui::ClipboardBuffer clipboard_buffer,
                                       const std::u16string& type,
                                       ReadCustomDataCallback callback) {
  if (!IsRendererPasteAllowed(render_frame_host())) {
    std::move(callback).Run(std::u16string());
    return;
  }
  std::u16string result;
  auto data_dst = CreateDataEndpoint();
  ui::Clipboard::GetForCurrentThread()->ReadCustomData(clipboard_buffer, type,
                                                       data_dst.get(), &result);

  std::string data = base::UTF16ToUTF8(result);
  PasteIfPolicyAllowed(
      clipboard_buffer, ui::ClipboardFormatType::WebCustomDataType(),
      std::move(data),
      base::BindOnce(
          [](std::u16string result, ReadCustomDataCallback callback,
             ClipboardPasteContentAllowed allowed) {
            if (!allowed)
              result.clear();
            std::move(callback).Run(result);
          },
          std::move(result), std::move(callback)));
}

void ClipboardHostImpl::WriteText(const std::u16string& text) {
  CopyIfAllowed(
      text.size() * sizeof(std::u16string::value_type),
      base::BindOnce(&ui::ScopedClipboardWriter::WriteText,
                     base::Unretained(clipboard_writer_.get()), text));
}

void ClipboardHostImpl::WriteHtml(const std::u16string& markup,
                                  const GURL& url) {
  CopyIfAllowed(markup.size() * sizeof(std::u16string::value_type),
                base::BindOnce(&ui::ScopedClipboardWriter::WriteHTML,
                               base::Unretained(clipboard_writer_.get()),
                               markup, url.spec()));
}

void ClipboardHostImpl::WriteSvg(const std::u16string& markup) {
  clipboard_writer_->WriteSvg(markup);
}

void ClipboardHostImpl::WriteSmartPasteMarker() {
  clipboard_writer_->WriteWebSmartPaste();
}

void ClipboardHostImpl::WriteCustomData(
    const base::flat_map<std::u16string, std::u16string>& data) {
  base::Pickle pickle;
  ui::WriteCustomDataToPickle(data, &pickle);
  clipboard_writer_->WritePickledData(
      pickle, ui::ClipboardFormatType::WebCustomDataType());
}

void ClipboardHostImpl::WriteBookmark(const std::string& url,
                                      const std::u16string& title) {
  clipboard_writer_->WriteBookmark(title, url);
}

void ClipboardHostImpl::WriteImage(const SkBitmap& bitmap) {
  clipboard_writer_->WriteImage(bitmap);
}

void ClipboardHostImpl::CommitWrite() {
  clipboard_writer_ = std::make_unique<ui::ScopedClipboardWriter>(
      ui::ClipboardBuffer::kCopyPaste, CreateDataEndpoint());
}

bool ClipboardHostImpl::IsUnsanitizedCustomFormatContentAllowed() {
  if (!base::FeatureList::IsEnabled(blink::features::kClipboardCustomFormats)) {
    mojo::ReportBadMessage("Custom format read/write is not enabled.");
    return false;
  }

  return render_frame_host().HasTransientUserActivation();
}

void ClipboardHostImpl::ReadAvailableCustomAndStandardFormats(
    ReadAvailableCustomAndStandardFormatsCallback callback) {
  if (!IsUnsanitizedCustomFormatContentAllowed())
    return;
  std::vector<std::u16string> format_types =
      ui::Clipboard::GetForCurrentThread()
          ->ReadAvailableStandardAndCustomFormatNames(
              ui::ClipboardBuffer::kCopyPaste, CreateDataEndpoint().get());
  std::move(callback).Run(format_types);
}

void ClipboardHostImpl::ReadUnsanitizedCustomFormat(
    const std::u16string& format,
    ReadUnsanitizedCustomFormatCallback callback) {
  if (!IsUnsanitizedCustomFormatContentAllowed())
    return;
  // `kMaxFormatSize` includes the null terminator as well so we check if
  // the `format` size is strictly less than `kMaxFormatSize` or not.
  if (format.length() >= blink::mojom::ClipboardHost::kMaxFormatSize)
    return;

  // Extract the custom format names and then query the web custom format
  // corresponding to the MIME type.
  std::string format_name = base::UTF16ToASCII(format);
  auto data_endpoint = CreateDataEndpoint();
  std::map<std::string, std::string> custom_format_names =
      ui::Clipboard::GetForCurrentThread()->ExtractCustomPlatformNames(
          ui::ClipboardBuffer::kCopyPaste, data_endpoint.get());
  std::string web_custom_format_string;
  if (custom_format_names.find(format_name) != custom_format_names.end())
    web_custom_format_string = custom_format_names[format_name];
  if (web_custom_format_string.empty())
    return;

  std::string result;
  ui::Clipboard::GetForCurrentThread()->ReadData(
      ui::ClipboardFormatType::GetType(web_custom_format_string),
      data_endpoint.get(), &result);
  if (result.size() >= blink::mojom::ClipboardHost::kMaxDataSize)
    return;
  base::span<const uint8_t> span = base::as_bytes(base::make_span(result));
  mojo_base::BigBuffer buffer = mojo_base::BigBuffer(span);
  std::move(callback).Run(std::move(buffer));
}

void ClipboardHostImpl::WriteUnsanitizedCustomFormat(
    const std::u16string& format,
    mojo_base::BigBuffer data) {
  if (!IsUnsanitizedCustomFormatContentAllowed())
    return;
  // `kMaxFormatSize` & `kMaxDataSize` includes the null terminator.
  if (format.length() >= blink::mojom::ClipboardHost::kMaxFormatSize)
    return;
  if (data.size() >= blink::mojom::ClipboardHost::kMaxDataSize)
    return;

  // The `format` is mapped to user agent defined web custom format before
  // writing to the clipboard. This happens in
  // `ScopedClipboardWriter::WriteData`.
  clipboard_writer_->WriteData(format, std::move(data));
}

void ClipboardHostImpl::PasteIfPolicyAllowed(
    ui::ClipboardBuffer clipboard_buffer,
    const ui::ClipboardFormatType& data_type,
    std::string data,
    IsClipboardPasteContentAllowedCallback callback) {
  if (data.empty()) {
    std::move(callback).Run(ClipboardPasteContentAllowed(true));
    return;
  }
  const size_t data_size = data.size();
  auto policy_cb =
      base::BindOnce(&ClipboardHostImpl::PasteIfPolicyAllowedCallback,
                     weak_ptr_factory_.GetWeakPtr(), clipboard_buffer,
                     data_type, std::move(data), std::move(callback));

  if (ui::DataTransferPolicyController::HasInstance()) {
    ui::DataTransferPolicyController::Get()->PasteIfAllowed(
        ui::Clipboard::GetForCurrentThread()->GetSource(clipboard_buffer),
        CreateDataEndpoint().get(), data_size, &render_frame_host(),
        std::move(policy_cb));
    return;
  }
  std::move(policy_cb).Run(/*is_allowed=*/true);
}

void ClipboardHostImpl::PasteIfPolicyAllowedCallback(
    ui::ClipboardBuffer clipboard_buffer,
    const ui::ClipboardFormatType& data_type,
    std::string data,
    IsClipboardPasteContentAllowedCallback callback,
    bool is_allowed) {
  if (is_allowed) {
    PerformPasteIfContentAllowed(
        ui::Clipboard::GetForCurrentThread()->GetSequenceNumber(
            clipboard_buffer),
        data_type, std::move(data), std::move(callback));
  } else {
    // If not allowed, then don't proceed with content checks.
    std::move(callback).Run(ClipboardPasteContentAllowed(false));
  }
}

void ClipboardHostImpl::PerformPasteIfContentAllowed(
    const ui::ClipboardSequenceNumberToken& seqno,
    const ui::ClipboardFormatType& data_type,
    std::string data,
    IsClipboardPasteContentAllowedCallback callback) {
  CleanupObsoleteRequests();
  // Add |callback| to the callbacks associated to the sequence number, adding
  // an entry to the map if one does not exist.
  auto& request = is_allowed_requests_[seqno];
  if (request.AddCallback(std::move(callback)))
    StartIsPasteContentAllowedRequest(seqno, data_type, std::move(data));
}

void ClipboardHostImpl::StartIsPasteContentAllowedRequest(
    const ui::ClipboardSequenceNumberToken& seqno,
    const ui::ClipboardFormatType& data_type,
    std::string data) {
  static_cast<RenderFrameHostImpl&>(render_frame_host())
      .IsClipboardPasteContentAllowed(
          data_type, data,
          base::BindOnce(&ClipboardHostImpl::FinishPasteIfContentAllowed,
                         weak_ptr_factory_.GetWeakPtr(), seqno));
}

void ClipboardHostImpl::FinishPasteIfContentAllowed(
    const ui::ClipboardSequenceNumberToken& seqno,
    ClipboardPasteContentAllowed allowed) {
  if (is_allowed_requests_.count(seqno) == 0)
    return;

  auto& request = is_allowed_requests_[seqno];
  request.Complete(allowed);
}

void ClipboardHostImpl::CopyIfAllowed(size_t data_size_in_bytes,
                                      CopyAllowedCallback callback) {
  std::u16string replacement_data;
  if (GetContentClient()->browser()->IsClipboardCopyAllowed(
          render_frame_host().GetBrowserContext(),
          render_frame_host().GetLastCommittedURL(), data_size_in_bytes,
          replacement_data)) {
    std::move(callback).Run();
  } else {
    clipboard_writer_->WriteText(replacement_data);
  }
}

void ClipboardHostImpl::CleanupObsoleteRequests() {
  for (auto it = is_allowed_requests_.begin();
       it != is_allowed_requests_.end();) {
    it = it->second.IsObsolete(base::Time::Now())
             ? is_allowed_requests_.erase(it)
             : std::next(it);
  }
}

std::unique_ptr<ui::DataTransferEndpoint>
ClipboardHostImpl::CreateDataEndpoint() {
  if (render_frame_host().GetBrowserContext()->IsOffTheRecord()) {
    return nullptr;
  }
  return std::make_unique<ui::DataTransferEndpoint>(
      render_frame_host().GetMainFrame()->GetLastCommittedURL(),
      render_frame_host().HasTransientUserActivation());
}
}  // namespace content
