chromium/chromeos/ui/clipboard_history/clipboard_history_util.cc

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromeos/ui/clipboard_history/clipboard_history_util.h"

#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/crosapi/mojom/clipboard_history.mojom.h"
#include "chromeos/ui/base/file_icon_util.h"
#include "chromeos/ui/vector_icons/vector_icons.h"
#include "components/vector_icons/vector_icons.h"
#include "ui/base/models/image_model.h"
#include "url/gurl.h"

namespace gfx {
struct VectorIcon;
}  // namespace gfx

namespace chromeos::clipboard_history {

namespace {

// The DIP size of a menu item icon that indicates the clipboard data format.
constexpr int kIconSize = 20;

QueryItemDescriptorsImpl& GetQueryItemDescriptorsImpl() {
  static base::NoDestructor<QueryItemDescriptorsImpl>
      query_item_descriptors_impl;
  return *query_item_descriptors_impl;
}

PasteClipboardItemByIdImpl& GetPasteClipboardItemByIdImpl() {
  static base::NoDestructor<PasteClipboardItemByIdImpl> paste_item_by_id_impl;
  return *paste_item_by_id_impl;
}

}  // namespace

bool IsUrl(const std::u16string& text) {
  return GURL(text).is_valid();
}

void SetQueryItemDescriptorsImpl(QueryItemDescriptorsImpl impl) {
  QueryItemDescriptorsImpl& old_impl = GetQueryItemDescriptorsImpl();
  CHECK(old_impl.is_null() || impl.is_null());
  old_impl = impl;
}

QueryItemDescriptorsImpl::ResultType QueryItemDescriptors() {
  // `SetQueryItemDescriptorsImpl()` may not have been called in unit tests.
  if (auto& query_callback = GetQueryItemDescriptorsImpl()) {
    return query_callback.Run();
  }

  return QueryItemDescriptorsImpl::ResultType();
}

void SetPasteClipboardItemByIdImpl(PasteClipboardItemByIdImpl impl) {
  PasteClipboardItemByIdImpl& old_impl = GetPasteClipboardItemByIdImpl();
  CHECK(old_impl.is_null() || impl.is_null());
  old_impl = impl;
}

void PasteClipboardItemById(
    const base::UnguessableToken& id,
    int event_flags,
    crosapi::mojom::ClipboardHistoryControllerShowSource paste_source) {
  // `SetPasteClipboardItemByIdImpl()` may not have been called in unit tests.
  if (auto& paste_callback = GetPasteClipboardItemByIdImpl()) {
    paste_callback.Run(id, event_flags, paste_source);
  }
}

ui::ImageModel GetIconForDescriptor(
    const crosapi::mojom::ClipboardHistoryItemDescriptor& descriptor) {
  const gfx::VectorIcon* icon = nullptr;
  switch (descriptor.display_format) {
    case crosapi::mojom::ClipboardHistoryDisplayFormat::kText:
      // TODO(http://b/275629173): Consider a new display format for URLs.
      icon = (features::IsClipboardHistoryRefreshEnabled() &&
              IsUrl(descriptor.display_text))
                 ? &vector_icons::kLinkIcon
                 : &kTextIcon;
      break;
    case crosapi::mojom::ClipboardHistoryDisplayFormat::kPng:
      icon = &kFiletypeImageIcon;
      break;
    case crosapi::mojom::ClipboardHistoryDisplayFormat::kHtml:
      icon = &vector_icons::kCodeIcon;
      break;
    case crosapi::mojom::ClipboardHistoryDisplayFormat::kFile: {
      // If `display_text` is the name of a single file, use the icon
      // corresponding to the file type, if any; otherwise, use a generic
      // multi-file icon.
      icon = descriptor.file_count == 1
                 ? &chromeos::GetIconForPath(base::FilePath(
                       base::UTF16ToUTF8(descriptor.display_text)))
                 : &vector_icons::kContentCopyIcon;
      break;
    }
    case crosapi::mojom::ClipboardHistoryDisplayFormat::kUnknown:
      NOTREACHED();
  }

  if (icon) {
    // TODO(b/278109818): Double-check the icon color.
    return ui::ImageModel::FromVectorIcon(*icon,
                                          /*color_id=*/ui::kColorSysSecondary,
                                          kIconSize);
  }

  NOTREACHED();
}

}  // namespace chromeos::clipboard_history