#include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h"
#include <optional>
#include <string>
#include <utility>
#include "base/functional/bind.h"
#include "base/lazy_instance.h"
#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
#include "build/chromeos_buildflags.h"
#include "extensions/browser/api/extensions_api_client.h"
#include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h"
#include "extensions/common/api/virtual_keyboard_private.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/clipboard/clipboard_history_item.h"
#include "base/barrier_closure.h"
#include "base/task/thread_pool.h"
#include "chromeos/crosapi/mojom/clipboard_history.mojom.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/webui/web_ui_util.h"
#include "ui/color/color_provider.h"
#endif
namespace extensions {
namespace {
const char kNotYetImplementedError[] = …;
const char kVirtualKeyboardNotEnabled[] = …;
const char kSetDraggableAreaFailed[] = …;
const char kSetAreaToRemainOnScreenFailed[] = …;
const char kSetWindowBoundsInScreenFailed[] = …;
const char kUnknownError[] = …;
#if BUILDFLAG(IS_CHROMEOS_ASH)
const char kGetClipboardHistoryFailed[] =
"Getting the clipboard history failed";
const char kPasteClipboardItemFailed[] = "Pasting the clipboard item failed";
const char kDeleteClipboardItemFailed[] = "Deleting the clipboard item failed";
#endif
keyboard;
gfx::Rect KeyboardBoundsToRect(const keyboard::Bounds& bounds) { … }
#if BUILDFLAG(IS_CHROMEOS_ASH)
using extensions::api::virtual_keyboard_private::ClipboardItem;
using extensions::api::virtual_keyboard_private::DisplayFormat;
void ConvertClipboardHistoryItemToClipboardItem(
base::OnceClosure barrier_callback,
const ui::ColorProvider& color_provider,
const ash::ClipboardHistoryItem& history_item,
std::vector<ClipboardItem>* items_ptr) {
ClipboardItem item;
item.id = history_item.id().ToString();
item.time_copied =
history_item.time_copied().InMillisecondsFSinceUnixEpochIgnoringNull();
switch (history_item.display_format()) {
case crosapi::mojom::ClipboardHistoryDisplayFormat::kUnknown:
NOTREACHED();
case crosapi::mojom::ClipboardHistoryDisplayFormat::kText:
item.text_data = base::UTF16ToUTF8(history_item.display_text());
item.display_format = DisplayFormat::kText;
break;
case crosapi::mojom::ClipboardHistoryDisplayFormat::kPng:
item.display_format = DisplayFormat::kPng;
break;
case crosapi::mojom::ClipboardHistoryDisplayFormat::kHtml:
item.display_format = DisplayFormat::kHtml;
break;
case crosapi::mojom::ClipboardHistoryDisplayFormat::kFile:
DCHECK(!item.image_data.has_value());
const auto& icon = history_item.icon();
DCHECK(icon.has_value());
item.image_data =
webui::GetBitmapDataUrl(*icon->Rasterize(&color_provider).bitmap());
item.text_data = base::UTF16ToUTF8(history_item.display_text());
item.display_format = DisplayFormat::kFile;
break;
}
items_ptr->push_back(std::move(item));
if (const auto& maybe_image = history_item.display_image()) {
const auto* const bitmap =
maybe_image->IsVectorIcon()
? maybe_image->Rasterize(&color_provider).bitmap()
: maybe_image->GetImage().ToSkBitmap();
base::ThreadPool::PostTask(
FROM_HERE,
base::BindOnce(
[](base::OnceClosure barrier_callback, ClipboardItem& item,
const SkBitmap& bitmap) {
item.image_data = webui::GetBitmapDataUrl(bitmap);
std::move(barrier_callback).Run();
},
std::move(barrier_callback), std::ref(items_ptr->back()), *bitmap));
} else {
std::move(barrier_callback).Run();
}
}
#endif
}
bool VirtualKeyboardPrivateFunction::PreRunValidation(std::string* error) { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateInsertTextFunction::Run() { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateSendKeyEventFunction::Run() { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateHideKeyboardFunction::Run() { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateSetHotrodKeyboardFunction::Run() { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateLockKeyboardFunction::Run() { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateKeyboardLoadedFunction::Run() { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateGetKeyboardConfigFunction::Run() { … }
void VirtualKeyboardPrivateGetKeyboardConfigFunction::OnKeyboardConfig(
std::optional<base::Value::Dict> results) { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateOpenSettingsFunction::Run() { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateOpenSuggestionSettingsFunction::Run() { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateSetContainerBehaviorFunction::Run() { … }
void VirtualKeyboardPrivateSetContainerBehaviorFunction::OnSetContainerBehavior(
bool success) { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateSetDraggableAreaFunction::Run() { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateSetKeyboardStateFunction::Run() { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateSetOccludedBoundsFunction::Run() { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateSetHitTestBoundsFunction::Run() { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateSetAreaToRemainOnScreenFunction::Run() { … }
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateSetWindowBoundsInScreenFunction::Run() { … }
VirtualKeyboardPrivateSetWindowBoundsInScreenFunction ::
~VirtualKeyboardPrivateSetWindowBoundsInScreenFunction() = default;
#if BUILDFLAG(IS_CHROMEOS_ASH)
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateGetClipboardHistoryFunction::Run() {
std::optional<keyboard::GetClipboardHistory::Params> params =
keyboard::GetClipboardHistory::Params::Create(args());
EXTENSION_FUNCTION_VALIDATE(params);
delegate()->GetClipboardHistory(base::BindOnce(
&VirtualKeyboardPrivateGetClipboardHistoryFunction::OnGetClipboardHistory,
this));
return did_respond() ? AlreadyResponded() : RespondLater();
}
void VirtualKeyboardPrivateGetClipboardHistoryFunction::OnGetClipboardHistory(
std::vector<ash::ClipboardHistoryItem> history_items) {
const auto* web_contents = GetSenderWebContents();
if (!web_contents) {
Respond(Error(kGetClipboardHistoryFailed));
return;
}
auto items = std::make_unique<ClipboardItems>();
items->reserve(history_items.size());
auto* items_ptr = items.get();
base::RepeatingClosure barrier = base::BarrierClosure(
history_items.size(),
base::BindPostTaskToCurrentDefault(
base::BindOnce(&VirtualKeyboardPrivateGetClipboardHistoryFunction::
OnClipboardHistoryItemsConverted,
this, std::move(items))));
for (const auto& history_item : history_items) {
ConvertClipboardHistoryItemToClipboardItem(
barrier, web_contents->GetColorProvider(), history_item, items_ptr);
}
}
void VirtualKeyboardPrivateGetClipboardHistoryFunction::
OnClipboardHistoryItemsConverted(std::unique_ptr<ClipboardItems> items) {
base::Value::List results;
for (const auto& item : *items) {
results.Append(item.ToValue());
}
Respond(WithArguments(std::move(results)));
}
VirtualKeyboardPrivateGetClipboardHistoryFunction ::
~VirtualKeyboardPrivateGetClipboardHistoryFunction() = default;
ExtensionFunction::ResponseAction
VirtualKeyboardPrivatePasteClipboardItemFunction::Run() {
std::optional<keyboard::PasteClipboardItem::Params> params =
keyboard::PasteClipboardItem::Params::Create(args());
EXTENSION_FUNCTION_VALIDATE(params);
if (!delegate()->PasteClipboardItem(params->item_id))
return RespondNow(Error(kPasteClipboardItemFailed));
return RespondNow(NoArguments());
}
VirtualKeyboardPrivatePasteClipboardItemFunction ::
~VirtualKeyboardPrivatePasteClipboardItemFunction() = default;
ExtensionFunction::ResponseAction
VirtualKeyboardPrivateDeleteClipboardItemFunction::Run() {
std::optional<keyboard::DeleteClipboardItem::Params> params =
keyboard::DeleteClipboardItem::Params::Create(args());
EXTENSION_FUNCTION_VALIDATE(params);
if (!delegate()->DeleteClipboardItem(params->item_id))
return RespondNow(Error(kDeleteClipboardItemFailed));
return RespondNow(NoArguments());
}
VirtualKeyboardPrivateDeleteClipboardItemFunction ::
~VirtualKeyboardPrivateDeleteClipboardItemFunction() = default;
#endif
VirtualKeyboardAPI::VirtualKeyboardAPI(content::BrowserContext* context) { … }
VirtualKeyboardAPI::~VirtualKeyboardAPI() = default;
static base::LazyInstance<BrowserContextKeyedAPIFactory<VirtualKeyboardAPI>>::
DestructorAtExit g_factory = …;
BrowserContextKeyedAPIFactory<VirtualKeyboardAPI>*
VirtualKeyboardAPI::GetFactoryInstance() { … }
}