#include "chromeos/ash/services/ime/decoder/decoder_engine.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/functional/callback_helpers.h"
#include "base/notimplemented.h"
#include "chromeos/ash/services/ime/constants.h"
namespace ash {
namespace ime {
namespace {
class ClientDelegate : public ImeClientDelegate {
public:
ClientDelegate(const std::string& ime_spec,
mojo::PendingRemote<mojom::InputChannel> remote)
: ime_spec_(ime_spec), client_remote_(std::move(remote)) {
client_remote_.set_disconnect_handler(base::BindOnce(
&ClientDelegate::OnDisconnected, base::Unretained(this)));
}
~ClientDelegate() override {}
void Unused1() override { NOTIMPLEMENTED(); }
void Process(const uint8_t* data, size_t size) override {
if (client_remote_ && client_remote_.is_bound()) {
std::vector<uint8_t> msg(data, UNSAFE_TODO(data + size));
client_remote_->ProcessMessage(msg, base::DoNothing());
}
}
void Destroy() override { delete this; }
private:
void OnDisconnected() {
client_remote_.reset();
LOG(ERROR) << "Client remote is disconnected." << ime_spec_;
}
std::string ime_spec_;
mojo::Remote<mojom::InputChannel> client_remote_;
};
}
DecoderEngine::DecoderEngine(
ImeCrosPlatform* platform,
std::optional<ImeSharedLibraryWrapper::EntryPoints> entry_points) {
if (!entry_points) {
LOG(WARNING) << "DecoderEngine INIT INCOMPLETE.";
return;
}
decoder_entry_points_ = *entry_points;
decoder_entry_points_->init_proto_mode(platform);
}
DecoderEngine::~DecoderEngine() {
if (!decoder_entry_points_) {
return;
}
decoder_entry_points_->close_proto_mode();
}
bool DecoderEngine::BindRequest(
const std::string& ime_spec,
mojo::PendingReceiver<mojom::InputChannel> receiver,
mojo::PendingRemote<mojom::InputChannel> remote,
const std::vector<uint8_t>& extra) {
if (decoder_entry_points_ &&
decoder_entry_points_->proto_mode_supports(ime_spec.c_str()) &&
decoder_entry_points_->proto_mode_activate_ime(
ime_spec.c_str(), new ClientDelegate(ime_spec, std::move(remote)))) {
decoder_channel_receivers_.Add(this, std::move(receiver));
return true;
}
return false;
}
void DecoderEngine::ProcessMessage(const std::vector<uint8_t>& message,
ProcessMessageCallback callback) {
std::vector<uint8_t> result;
if (decoder_entry_points_) {
decoder_entry_points_->proto_mode_process(message.data(), message.size());
}
std::move(callback).Run(result);
}
}
}