blob: 7ae91489fbaba880817c96ac5213943ecd0833ea [file] [log] [blame]
// Copyright 2018 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 "tools/fuchsia/fidlgen_js/runtime/zircon.h"
#include <lib/zx/channel.h>
#include <zircon/errors.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>
#include "base/bind.h"
#include "gin/arguments.h"
#include "gin/array_buffer.h"
#include "gin/converter.h"
#include "gin/data_object_builder.h"
#include "gin/function_template.h"
namespace {
v8::Local<v8::Object> ZxChannelCreate(v8::Isolate* isolate) {
zx::channel c1, c2;
zx_status_t status = zx::channel::create(0, &c1, &c2);
return gin::DataObjectBuilder(isolate)
.Set("status", status)
.Set("first", c1.release())
.Set("second", c2.release())
.Build();
}
zx_status_t ZxChannelWrite(gin::Arguments* args) {
zx_handle_t handle;
if (!args->GetNext(&handle)) {
args->ThrowError();
return ZX_ERR_INVALID_ARGS;
}
gin::ArrayBufferView data;
if (!args->GetNext(&data)) {
args->ThrowError();
return ZX_ERR_INVALID_ARGS;
}
std::vector<zx_handle_t> handles;
if (!args->GetNext(&handles)) {
args->ThrowError();
return ZX_ERR_INVALID_ARGS;
}
zx_status_t status =
zx_channel_write(handle, 0, data.bytes(), data.num_bytes(),
handles.data(), handles.size());
return status;
}
v8::Local<v8::Value> StrToUtf8Array(gin::Arguments* args) {
std::string str;
// This converts the string to utf8 from ucs2, so then just repackage the
// string as an array and return it.
if (!args->GetNext(&str)) {
args->ThrowError();
return v8::Local<v8::Object>();
}
// TODO(crbug.com/883496): Not sure how to make a Uint8Array to return here
// which would be a bit more efficient.
std::vector<int> data;
std::copy(str.begin(), str.end(), std::back_inserter(data));
return gin::ConvertToV8(args->isolate(), data);
}
v8::Local<v8::Object> GetOrCreateZxObject(v8::Isolate* isolate,
v8::Local<v8::Object> global) {
v8::Local<v8::Object> zx;
v8::Local<v8::Value> zx_value = global->Get(gin::StringToV8(isolate, "zx"));
if (zx_value.IsEmpty() || !zx_value->IsObject()) {
zx = v8::Object::New(isolate);
global->Set(gin::StringToSymbol(isolate, "zx"), zx);
} else {
zx = v8::Local<v8::Object>::Cast(zx);
}
return zx;
}
} // namespace
namespace fidljs {
void InjectZxBindings(v8::Isolate* isolate, v8::Local<v8::Object> global) {
v8::Local<v8::Object> zx = GetOrCreateZxObject(isolate, global);
#define SET_CONSTANT(k) \
zx->Set(gin::StringToSymbol(isolate, #k), gin::ConvertToV8(isolate, k))
// zx_status_t.
SET_CONSTANT(ZX_OK);
SET_CONSTANT(ZX_ERR_INTERNAL);
SET_CONSTANT(ZX_ERR_NOT_SUPPORTED);
SET_CONSTANT(ZX_ERR_NO_RESOURCES);
SET_CONSTANT(ZX_ERR_NO_MEMORY);
SET_CONSTANT(ZX_ERR_INTERNAL_INTR_RETRY);
SET_CONSTANT(ZX_ERR_INVALID_ARGS);
SET_CONSTANT(ZX_ERR_BAD_HANDLE);
SET_CONSTANT(ZX_ERR_WRONG_TYPE);
SET_CONSTANT(ZX_ERR_BAD_SYSCALL);
SET_CONSTANT(ZX_ERR_OUT_OF_RANGE);
SET_CONSTANT(ZX_ERR_BUFFER_TOO_SMALL);
SET_CONSTANT(ZX_ERR_BAD_STATE);
SET_CONSTANT(ZX_ERR_TIMED_OUT);
SET_CONSTANT(ZX_ERR_SHOULD_WAIT);
SET_CONSTANT(ZX_ERR_CANCELED);
SET_CONSTANT(ZX_ERR_PEER_CLOSED);
SET_CONSTANT(ZX_ERR_NOT_FOUND);
SET_CONSTANT(ZX_ERR_ALREADY_EXISTS);
SET_CONSTANT(ZX_ERR_ALREADY_BOUND);
SET_CONSTANT(ZX_ERR_UNAVAILABLE);
SET_CONSTANT(ZX_ERR_ACCESS_DENIED);
SET_CONSTANT(ZX_ERR_IO);
SET_CONSTANT(ZX_ERR_IO_REFUSED);
SET_CONSTANT(ZX_ERR_IO_DATA_INTEGRITY);
SET_CONSTANT(ZX_ERR_IO_DATA_LOSS);
SET_CONSTANT(ZX_ERR_IO_NOT_PRESENT);
SET_CONSTANT(ZX_ERR_IO_OVERRUN);
SET_CONSTANT(ZX_ERR_IO_MISSED_DEADLINE);
SET_CONSTANT(ZX_ERR_IO_INVALID);
SET_CONSTANT(ZX_ERR_BAD_PATH);
SET_CONSTANT(ZX_ERR_NOT_DIR);
SET_CONSTANT(ZX_ERR_NOT_FILE);
SET_CONSTANT(ZX_ERR_FILE_BIG);
SET_CONSTANT(ZX_ERR_NO_SPACE);
SET_CONSTANT(ZX_ERR_NOT_EMPTY);
SET_CONSTANT(ZX_ERR_STOP);
SET_CONSTANT(ZX_ERR_NEXT);
SET_CONSTANT(ZX_ERR_ASYNC);
SET_CONSTANT(ZX_ERR_PROTOCOL_NOT_SUPPORTED);
SET_CONSTANT(ZX_ERR_ADDRESS_UNREACHABLE);
SET_CONSTANT(ZX_ERR_ADDRESS_IN_USE);
SET_CONSTANT(ZX_ERR_NOT_CONNECTED);
SET_CONSTANT(ZX_ERR_CONNECTION_REFUSED);
SET_CONSTANT(ZX_ERR_CONNECTION_RESET);
SET_CONSTANT(ZX_ERR_CONNECTION_ABORTED);
// Handle APIs.
zx->Set(gin::StringToSymbol(isolate, "handleClose"),
gin::CreateFunctionTemplate(isolate,
base::BindRepeating(&zx_handle_close))
->GetFunction());
SET_CONSTANT(ZX_HANDLE_INVALID);
// Channel APIs.
zx->Set(gin::StringToSymbol(isolate, "channelCreate"),
gin::CreateFunctionTemplate(isolate,
base::BindRepeating(&ZxChannelCreate))
->GetFunction());
zx->Set(
gin::StringToSymbol(isolate, "channelWrite"),
gin::CreateFunctionTemplate(isolate, base::BindRepeating(&ZxChannelWrite))
->GetFunction());
SET_CONSTANT(ZX_CHANNEL_READABLE);
SET_CONSTANT(ZX_CHANNEL_WRITABLE);
SET_CONSTANT(ZX_CHANNEL_PEER_CLOSED);
SET_CONSTANT(ZX_CHANNEL_READ_MAY_DISCARD);
SET_CONSTANT(ZX_CHANNEL_MAX_MSG_BYTES);
SET_CONSTANT(ZX_CHANNEL_MAX_MSG_HANDLES);
// Utility to make string handling easier to convert from a UCS2 JS string to
// an array of UTF-8 (which is how strings are represented in FIDL).
// TODO(crbug.com/883496): This is not really zx, should move to a generic
// runtime helper file if there are more similar C++ helpers required.
zx->Set(
gin::StringToSymbol(isolate, "strToUtf8Array"),
gin::CreateFunctionTemplate(isolate, base::BindRepeating(&StrToUtf8Array))
->GetFunction());
#undef SET_CONSTANT
}
} // namespace fidljs