blob: 28acb1f554cf286d76e5243d168809927ff438de [file] [log] [blame]
// 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 "ui/ozone/platform/wayland/test/test_data_source.h"
#include <wayland-server-core.h>
#include <cstdint>
#include <utility>
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/task_runner_util.h"
namespace wl {
namespace {
std::vector<uint8_t> ReadDataOnWorkerThread(base::ScopedFD fd) {
constexpr size_t kChunkSize = 1024;
std::vector<uint8_t> bytes;
while (true) {
uint8_t chunk[kChunkSize];
ssize_t bytes_read = HANDLE_EINTR(read(fd.get(), chunk, kChunkSize));
if (bytes_read > 0) {
bytes.insert(bytes.end(), chunk, chunk + bytes_read);
continue;
}
if (bytes_read < 0) {
PLOG(ERROR) << "Failed to read data";
bytes.clear();
}
break;
}
return bytes;
}
void DataSourceOffer(wl_client* client,
wl_resource* resource,
const char* mime_type) {
GetUserDataAs<TestDataSource>(resource)->Offer(mime_type);
}
void DataSourceDestroy(wl_client* client, wl_resource* resource) {
wl_resource_destroy(resource);
}
void DataSourceSetActions(wl_client* client,
wl_resource* resource,
uint32_t dnd_actions) {
GetUserDataAs<TestDataSource>(resource)->SetActions(dnd_actions);
}
} // namespace
const struct wl_data_source_interface kTestDataSourceImpl = {
DataSourceOffer, DataSourceDestroy, DataSourceSetActions};
TestDataSource::TestDataSource(wl_resource* resource)
: ServerObject(resource),
task_runner_(
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})) {}
TestDataSource::~TestDataSource() {}
void TestDataSource::Offer(const std::string& mime_type) {
mime_types_.push_back(mime_type);
}
void TestDataSource::SetActions(uint32_t dnd_actions) {
actions_ |= dnd_actions;
}
void TestDataSource::ReadData(const std::string& mime_type,
ReadDataCallback callback) {
base::ScopedFD read_fd;
base::ScopedFD write_fd;
PCHECK(base::CreatePipe(&read_fd, &write_fd));
// 1. Send the SEND event to notify client's DataSource that it's time
// to send us the drag data thrhough the write_fd file descriptor.
wl_data_source_send_send(resource(), mime_type.c_str(), write_fd.get());
wl_client_flush(wl_resource_get_client(resource()));
// 2. Schedule the ReadDataOnWorkerThread task. The result of read
// operation will be then passed in to the callback requested by the caller.
base::PostTaskAndReplyWithResult(
task_runner_.get(), FROM_HERE,
base::BindOnce(&ReadDataOnWorkerThread, std::move(read_fd)),
std::move(callback));
}
void TestDataSource::OnCancelled() {
wl_data_source_send_cancelled(resource());
}
} // namespace wl