Skip to content

Commit

Permalink
Copy //runtime/dart/utils from Topaz into the engine. (flutter#8871)
Browse files Browse the repository at this point in the history
Build rules and include paths have been updated as necessary. No other functional change.
  • Loading branch information
chinmaygarde authored May 7, 2019
1 parent 149b7b8 commit d717044
Show file tree
Hide file tree
Showing 15 changed files with 714 additions and 0 deletions.
12 changes: 12 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
44 changes: 44 additions & 0 deletions shell/platform/fuchsia/runtime/dart/utils/BUILD.gn
Original file line number Diff line number Diff line change
@@ -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" ]
}
78 changes: 78 additions & 0 deletions shell/platform/fuchsia/runtime/dart/utils/files.cc
Original file line number Diff line number Diff line change
@@ -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
27 changes: 27 additions & 0 deletions shell/platform/fuchsia/runtime/dart/utils/files.h
Original file line number Diff line number Diff line change
@@ -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_
139 changes: 139 additions & 0 deletions shell/platform/fuchsia/runtime/dart/utils/handle_exception.cc
Original file line number Diff line number Diff line change
@@ -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
34 changes: 34 additions & 0 deletions shell/platform/fuchsia/runtime/dart/utils/handle_exception.h
Original file line number Diff line number Diff line change
@@ -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_
32 changes: 32 additions & 0 deletions shell/platform/fuchsia/runtime/dart/utils/inlines.h
Original file line number Diff line number Diff line change
@@ -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_
15 changes: 15 additions & 0 deletions shell/platform/fuchsia/runtime/dart/utils/logging.h
Original file line number Diff line number Diff line change
@@ -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_
Loading

0 comments on commit d717044

Please sign in to comment.