Copy //runtime/dart/utils from Topaz into the engine. (flutter/engine#8871)

Build rules and include paths have been updated as necessary. No other functional change.
This commit is contained in:
Chinmay Garde 2019-05-07 13:59:43 -07:00 committed by GitHub
parent 3da5268f4c
commit fa8b1de1c0
15 changed files with 714 additions and 0 deletions

View File

@ -715,6 +715,18 @@ FILE: ../../../flutter/shell/platform/embedder/platform_view_embedder.cc
FILE: ../../../flutter/shell/platform/embedder/platform_view_embedder.h
FILE: ../../../flutter/shell/platform/embedder/vsync_waiter_embedder.cc
FILE: ../../../flutter/shell/platform/embedder/vsync_waiter_embedder.h
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/files.cc
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/files.h
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exception.cc
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exception.h
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/inlines.h
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/logging.h
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.cc
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.h
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/vmo.cc
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/vmo.h
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/vmservice_object.cc
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/vmservice_object.h
FILE: ../../../flutter/shell/platform/glfw/client_wrapper/flutter_window_controller.cc
FILE: ../../../flutter/shell/platform/glfw/client_wrapper/flutter_window_controller_unittests.cc
FILE: ../../../flutter/shell/platform/glfw/client_wrapper/include/flutter/flutter_window.h

View File

@ -0,0 +1,44 @@
# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
assert(is_fuchsia)
import("//build/fuchsia/sdk.gni")
config("utils_config") {
include_dirs = [ "../../.." ]
}
source_set("utils") {
sources = [
"files.cc",
"files.h",
"handle_exception.cc",
"handle_exception.h",
"inlines.h",
"logging.h",
"tempfs.cc",
"tempfs.h",
"vmo.cc",
"vmo.h",
"vmservice_object.cc",
"vmservice_object.h",
]
deps = [
"$fuchsia_sdk_root/fidl:fuchsia.crash",
"$fuchsia_sdk_root/fidl:fuchsia.mem",
"$fuchsia_sdk_root/pkg:async-loop",
"$fuchsia_sdk_root/pkg:async-loop-cpp",
"$fuchsia_sdk_root/pkg:fdio",
"$fuchsia_sdk_root/pkg:memfs",
"$fuchsia_sdk_root/pkg:syslog",
"$fuchsia_sdk_root/pkg:zx",
"$fuchsia_sdk_root/pkg/lib/sys/cpp",
"$fuchsia_sdk_root/pkg/lib/vfs/cpp",
"//third_party/tonic",
]
public_configs = [ ":utils_config" ]
}

View File

@ -0,0 +1,78 @@
// Copyright 2013 The Flutter 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 "runtime/dart/utils/files.h"
#include <fcntl.h>
#include <stdint.h>
#include "runtime/dart/utils/inlines.h"
#include "runtime/dart/utils/logging.h"
namespace dart_utils {
namespace {
bool ReadFileDescriptor(int fd, std::string* result) {
DEBUG_CHECK(result, LOG_TAG, "");
result->clear();
if (fd < 0) {
return false;
}
constexpr size_t kBufferSize = 1 << 16;
size_t offset = 0;
ssize_t bytes_read = 0;
do {
offset += bytes_read;
result->resize(offset + kBufferSize);
bytes_read = read(fd, &(*result)[offset], kBufferSize);
} while (bytes_read > 0);
if (bytes_read < 0) {
result->clear();
return false;
}
result->resize(offset + bytes_read);
return true;
}
bool WriteFileDescriptor(int fd, const char* data, ssize_t size) {
ssize_t total = 0;
for (ssize_t partial = 0; total < size; total += partial) {
partial = write(fd, data + total, size - total);
if (partial < 0)
return false;
}
return true;
}
} // namespace
bool ReadFileToString(const std::string& path, std::string* result) {
return ReadFileToStringAt(AT_FDCWD, path, result);
}
bool ReadFileToStringAt(int dirfd,
const std::string& path,
std::string* result) {
int fd = openat(dirfd, path.c_str(), O_RDONLY);
bool status = ReadFileDescriptor(fd, result);
close(fd);
return status;
}
bool WriteFile(const std::string& path, const char* data, ssize_t size) {
int fd = openat(AT_FDCWD, path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0666);
if (fd < 0) {
return false;
}
bool status = WriteFileDescriptor(fd, data, size);
close(fd);
return status;
}
} // namespace dart_utils

View File

@ -0,0 +1,27 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_FILES_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_FILES_H_
#include <string>
namespace dart_utils {
// Reads the contents of the file at the given path or file descriptor and
// stores the data in result. Returns true if the file was read successfully,
// otherwise returns false. If this function returns false, |result| will be
// the empty string.
bool ReadFileToString(const std::string& path, std::string* result);
bool ReadFileToStringAt(int dirfd,
const std::string& path,
std::string* result);
// Writes the given data to the file at the given path. Returns true if the data
// was successfully written, otherwise returns false.
bool WriteFile(const std::string& path, const char* data, ssize_t size);
} // namespace dart_utils
#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_FILES_H_

View File

@ -0,0 +1,139 @@
// Copyright 2013 The Flutter 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 "runtime/dart/utils/handle_exception.h"
#include <string>
#include <fuchsia/crash/cpp/fidl.h>
#include <fuchsia/mem/cpp/fidl.h>
#include <lib/syslog/global.h>
#include <lib/zx/vmo.h>
#include <sys/types.h>
#include <third_party/tonic/converter/dart_converter.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include "runtime/dart/utils/logging.h"
namespace {
static bool FillBuffer(const std::string& data, fuchsia::mem::Buffer* buffer) {
uint64_t num_bytes = data.size();
zx::vmo vmo;
if (zx::vmo::create(num_bytes, 0u, &vmo) < 0) {
return false;
}
if (num_bytes > 0) {
if (vmo.write(data.data(), 0, num_bytes) < 0) {
return false;
}
}
buffer->vmo = std::move(vmo);
buffer->size = num_bytes;
return true;
}
template <typename T, size_t N>
void CopyToArray(const std::string& s, std::array<T, N>* arr) {
const size_t max_size = arr->size();
auto end = s.end();
if (s.size() > max_size) {
FX_LOGF(WARNING, LOG_TAG, "truncating '%s' to %d characters", s.c_str(),
max_size);
end = s.begin() + max_size;
}
std::copy(s.begin(), end, arr->data());
}
fuchsia::crash::ManagedRuntimeException BuildException(
const std::string& error,
const std::string& stack_trace) {
// The runtime type has already been pre-pended to the error message so we
// expect the format to be '$RuntimeType: $Message'.
std::string error_type;
std::string error_message;
const size_t delimiter_pos = error.find_first_of(':');
if (delimiter_pos == std::string::npos) {
FX_LOGF(ERROR, LOG_TAG,
"error parsing Dart exception: expected format '$RuntimeType: "
"$Message', got '%s'",
error.c_str());
// We still need to specify a type, otherwise the stack trace does not
// show up in the crash server UI.
error_type = "UnknownError";
error_message = error;
} else {
error_type = error.substr(0, delimiter_pos);
error_message =
error.substr(delimiter_pos + 2 /*to get rid of the leading ': '*/);
}
// Default-initialize to initialize the underlying arrays of characters with
// 0s and null-terminate the strings.
fuchsia::crash::GenericException exception = {};
CopyToArray(error_type, &exception.type);
CopyToArray(error_message, &exception.message);
if (!FillBuffer(stack_trace, &exception.stack_trace)) {
FX_LOG(ERROR, LOG_TAG, "Failed to convert Dart stack trace to VMO");
}
fuchsia::crash::ManagedRuntimeException dart_exception;
dart_exception.set_dart(std::move(exception));
return dart_exception;
}
} // namespace
namespace dart_utils {
zx_status_t HandleIfException(std::shared_ptr<::sys::ServiceDirectory> services,
const std::string& component_url,
Dart_Handle result) {
if (!Dart_IsError(result) || !Dart_ErrorHasException(result)) {
return ZX_OK;
}
const std::string error =
tonic::StdStringFromDart(Dart_ToString(Dart_ErrorGetException(result)));
const std::string stack_trace =
tonic::StdStringFromDart(Dart_ToString(Dart_ErrorGetStackTrace(result)));
return HandleException(services, component_url, error, stack_trace);
}
zx_status_t HandleException(std::shared_ptr<::sys::ServiceDirectory> services,
const std::string& component_url,
const std::string& error,
const std::string& stack_trace) {
fuchsia::crash::ManagedRuntimeException exception =
BuildException(error, stack_trace);
fuchsia::crash::AnalyzerSyncPtr analyzer;
services->Connect(analyzer.NewRequest());
#ifndef NDEBUG
if (!analyzer) {
FX_LOG(FATAL, LOG_TAG, "Could not connect to analyzer service");
}
#endif
fuchsia::crash::Analyzer_OnManagedRuntimeException_Result out_result;
const zx_status_t status = analyzer->OnManagedRuntimeException(
component_url, std::move(exception), &out_result);
if (status != ZX_OK) {
FX_LOGF(ERROR, LOG_TAG, "Failed to connect to crash analyzer: %d (%s)",
status, zx_status_get_string(status));
return ZX_ERR_INTERNAL;
} else if (out_result.is_err()) {
FX_LOGF(ERROR, LOG_TAG, "Failed to handle Dart exception: %d (%s)",
out_result.err(), zx_status_get_string(out_result.err()));
return ZX_ERR_INTERNAL;
}
return ZX_OK;
}
} // namespace dart_utils

View File

@ -0,0 +1,34 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_HANDLE_EXCEPTION_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_HANDLE_EXCEPTION_H_
#include <memory>
#include <string>
#include <lib/sys/cpp/service_directory.h>
#include <sys/types.h>
#include <third_party/dart/runtime/include/dart_api.h>
namespace dart_utils {
// If |result| is a Dart Exception, passes the exception message and stack trace
// to the crash analyzer service for further handling.
//
// Otherwise early returns with OK status.
zx_status_t HandleIfException(std::shared_ptr<::sys::ServiceDirectory> services,
const std::string& component_url,
Dart_Handle result);
// Passes the exception message and stack trace to the crash analyzer service
// for further handling.
zx_status_t HandleException(std::shared_ptr<::sys::ServiceDirectory> services,
const std::string& component_url,
const std::string& error,
const std::string& stack_trace);
} // namespace dart_utils
#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_HANDLE_EXCEPTION_H_

View File

@ -0,0 +1,32 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_INLINES_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_INLINES_H_
#include <lib/syslog/global.h>
namespace dart_utils {
inline void Check(bool condition, const char* tag, const char* message = "") {
if (!condition) {
FX_LOG(FATAL, tag, message);
}
}
#ifndef NDEBUG
#define DEBUG_CHECK(condition, tag, message) \
dart_utils::Check(condition, tag, message)
#else
#define DEBUG_CHECK(condition, tag, message) (true || (condition))
#endif
template <size_t SIZE, typename T>
inline size_t ArraySize(T (&array)[SIZE]) {
return SIZE;
}
} // namespace dart_utils
#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_INLINES_H_

View File

@ -0,0 +1,15 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_LOGGING_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_LOGGING_H_
namespace dart_utils {
// Use to mark logs published via the syslog API.
#define LOG_TAG "dart-utils"
} // namespace dart_utils
#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_LOGGING_H_

View File

@ -0,0 +1,33 @@
#!/boot/bin/sh
# Copyright 2013 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -x
# Kill any existing dart runners.
killall dart* || true
# Start up a dart runner app that is guaranteed to be JIT, non-product, and
# won't terminate.
run -d fuchsia-pkg://fuchsia.com/hello_dart_jit#meta/hello_dart_jit.cmx
# Wait for it to come up.
sleep 2
# Find the path to its vm service port.
# NB: This is the command used by the Flutter host-side command line tools.
# If the use of 'find' here breaks, the Flutter host-side command line tools
# will also be broken. If this is intentional, then craft and land a Flutter PR.
# See: https://github.com/flutter/flutter/commit/b18a2b1794606a6cddb6d7f3486557e473e3bfbb
# Then, land a hard transition to GI that updates Flutter and this test.
FIND_RESULT=`find /hub -name vmservice-port | grep dart_jit_runner`
echo "find result:\n${FIND_RESULT}"
killall dart* || true
if [ -z "${FIND_RESULT}" ]; then
echo "FAILURE: Dart VM service not found in the Hub!"
exit 1
fi
exit 0

View File

@ -0,0 +1,89 @@
// Copyright 2013 The Flutter 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 "runtime/dart/utils/tempfs.h"
#include <string>
#include <thread>
#include <lib/async-loop/cpp/loop.h>
#include <lib/fdio/namespace.h>
#include <lib/memfs/memfs.h>
#include <lib/syslog/global.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include "runtime/dart/utils/logging.h"
namespace {
constexpr char kTmpPath[] = "/tmp";
[[maybe_unused]] constexpr size_t kMaxTmpPages = 1024;
void DispatchTempMemFS() {
async::Loop loop(&kAsyncLoopConfigAttachToThread);
#if defined(DART_PRODUCT)
zx_status_t status = memfs_install_at_with_page_limit(loop.dispatcher(),
kMaxTmpPages, kTmpPath);
#else
// Hot reload uses /tmp to hold the updated dills and assets so do not
// impose any size limitation in non product runners.
zx_status_t status = memfs_install_at(loop.dispatcher(), kTmpPath);
#endif
if (status != ZX_OK) {
FX_LOGF(ERROR, LOG_TAG, "Failed to install a /tmp memfs: %s",
zx_status_get_string(status));
return;
}
loop.Run();
}
} // namespace
namespace dart_utils {
// Set up a memfs bound to /tmp in the process-wide namespace that has the
// lifetime of the process.
void SetupRunnerTemp() {
std::thread thread(DispatchTempMemFS);
thread.detach();
}
void SetupComponentTemp(fdio_ns_t* ns) {
// TODO(zra): Should isolates share a /tmp file system within a process, or
// should isolates each get their own private memfs for /tmp? For now,
// sharing the process-wide /tmp simplifies hot reload since the hot reload
// devfs requires sharing between the service isolate and the app isolates.
zx_status_t status;
fdio_flat_namespace_t* rootns;
status = fdio_ns_export_root(&rootns);
if (status != ZX_OK) {
FX_LOGF(ERROR, LOG_TAG, "Failed to export root ns: %s",
zx_status_get_string(status));
return;
}
zx_handle_t tmp_dir_handle;
for (size_t i = 0; i < rootns->count; i++) {
if (strcmp(rootns->path[i], kTmpPath) == 0) {
tmp_dir_handle = rootns->handle[i];
} else {
zx_handle_close(rootns->handle[i]);
rootns->handle[i] = ZX_HANDLE_INVALID;
}
}
free(rootns);
rootns = nullptr;
status = fdio_ns_bind(ns, kTmpPath, tmp_dir_handle);
if (status != ZX_OK) {
zx_handle_close(tmp_dir_handle);
FX_LOGF(ERROR, LOG_TAG,
"Failed to bind /tmp directory into isolate namespace: %s",
zx_status_get_string(status));
}
}
} // namespace dart_utils

View File

@ -0,0 +1,24 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_TEMPFS_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_TEMPFS_H_
#include <lib/fdio/namespace.h>
// Utility functions that set up /tmp for the dart_runner and flutter_runner.
namespace dart_utils {
// Set up a memfs bound to /tmp in the process-wide namespace that has the
// lifetime of the process.
void SetupRunnerTemp();
// Take the memfs mapped into the process-wide namespace for /tmp, and map it to
// /tmp in the given namespace.
void SetupComponentTemp(fdio_ns_t* ns);
} // namespace dart_utils
#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_TEMPFS_H_

View File

@ -0,0 +1,74 @@
// Copyright 2013 The Flutter 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 "runtime/dart/utils/vmo.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <fuchsia/mem/cpp/fidl.h>
#include <lib/fdio/io.h>
#include <lib/syslog/global.h>
#include "runtime/dart/utils/logging.h"
namespace {
bool VmoFromFd(int fd, fuchsia::mem::Buffer* buffer) {
if (!buffer) {
FX_LOG(FATAL, LOG_TAG, "Invalid buffer pointer");
}
struct stat stat_struct;
if (fstat(fd, &stat_struct) == -1) {
FX_LOGF(ERROR, LOG_TAG, "fstat failed: %s", strerror(errno));
return false;
}
zx_handle_t result = ZX_HANDLE_INVALID;
if (fdio_get_vmo_copy(fd, &result) != ZX_OK) {
return false;
}
buffer->vmo = zx::vmo(result);
buffer->size = stat_struct.st_size;
return true;
}
} // namespace
namespace dart_utils {
bool VmoFromFilename(const std::string& filename,
fuchsia::mem::Buffer* buffer) {
return VmoFromFilenameAt(AT_FDCWD, filename, buffer);
}
bool VmoFromFilenameAt(int dirfd,
const std::string& filename,
fuchsia::mem::Buffer* buffer) {
int fd = openat(dirfd, filename.c_str(), O_RDONLY);
if (fd == -1) {
FX_LOGF(ERROR, LOG_TAG, "openat(\"%s\") failed: %s", filename.c_str(),
strerror(errno));
return false;
}
bool result = VmoFromFd(fd, buffer);
close(fd);
return result;
}
zx_status_t IsSizeValid(const fuchsia::mem::Buffer& buffer, bool* is_valid) {
size_t vmo_size;
zx_status_t status = buffer.vmo.get_size(&vmo_size);
if (status == ZX_OK) {
*is_valid = vmo_size >= buffer.size;
} else {
*is_valid = false;
}
return status;
}
} // namespace dart_utils

View File

@ -0,0 +1,24 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_VMO_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_VMO_H_
#include <string>
#include <fuchsia/mem/cpp/fidl.h>
namespace dart_utils {
bool VmoFromFilename(const std::string& filename, fuchsia::mem::Buffer* buffer);
bool VmoFromFilenameAt(int dirfd,
const std::string& filename,
fuchsia::mem::Buffer* buffer);
zx_status_t IsSizeValid(const fuchsia::mem::Buffer& buffer, bool* is_valid);
} // namespace dart_utils
#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_VMO_H_

View File

@ -0,0 +1,63 @@
// Copyright 2013 The Flutter 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 "runtime/dart/utils/vmservice_object.h"
#include <dirent.h>
#include <errno.h>
#include <string>
#include <fuchsia/io/cpp/fidl.h>
#include <lib/syslog/global.h>
#include <zircon/status.h>
#include "runtime/dart/utils/logging.h"
namespace {
bool ReadDirContents(const std::string& path, std::vector<std::string>* out) {
out->clear();
DIR* dir = opendir(path.c_str());
if (!dir) {
return false;
}
struct dirent* de;
errno = 0;
while ((de = readdir(dir)) != nullptr) {
out->push_back(de->d_name);
}
closedir(dir);
return !errno;
}
} // namespace
namespace dart_utils {
void VMServiceObject::GetContents(LazyEntryVector* out_vector) const {
// List /tmp/dart.services if it exists, and push its contents as
// as the conrtents of this directory.
std::vector<std::string> files;
if (!ReadDirContents(kPortDir, &files)) {
FX_LOGF(ERROR, LOG_TAG,
"Failed to read Dart VM Service port directory '%s': %s", kPortDir,
strerror(errno));
return;
}
for (const auto& file : files) {
if ((file == ".") || (file == "..")) {
continue;
}
out_vector->push_back({std::stoul(file) + GetStartingId(), file,
fuchsia::io::MODE_TYPE_FILE});
}
}
zx_status_t VMServiceObject::GetFile(Node** out_node,
uint64_t id,
std::string name) const {
return ZX_ERR_NOT_FOUND;
}
} // namespace dart_utils

View File

@ -0,0 +1,26 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_VMSERVICE_OBJECT_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_VMSERVICE_OBJECT_H_
#include <lib/vfs/cpp/lazy_dir.h>
namespace dart_utils {
class VMServiceObject : public vfs::LazyDir {
public:
static constexpr const char* kDirName = "DartVM";
static constexpr const char* kPortDirName = "vmservice-port";
static constexpr const char* kPortDir = "/tmp/dart.services";
void GetContents(LazyEntryVector* out_vector) const override;
zx_status_t GetFile(Node** out_node,
uint64_t id,
std::string name) const override;
};
} // namespace dart_utils
#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_RUNTIME_DART_UTILS_VMSERVICE_OBJECT_H_