blob: cbd5114be5aae0761c15aec0a59706972b8dab78 [file] [log] [blame]
// Copyright 2017 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.
#include "lib/ui/flutter/sdk_ext/src/natives.h"
#include <stdio.h>
#include <string.h>
#include <memory>
#include <vector>
#include "dart-pkg/zircon/sdk_ext/handle.h"
#include "lib/fxl/arraysize.h"
#include "lib/fxl/logging.h"
#include "lib/fxl/macros.h"
namespace mozart {
#define REGISTER_FUNCTION(name, count) {"" #name, name, count},
#define DECLARE_FUNCTION(name, count) \
extern void name(Dart_NativeArguments args);
#define SCENIC_NATIVE_LIST(V) V(Scenic_offerServiceProvider, 3)
SCENIC_NATIVE_LIST(DECLARE_FUNCTION);
static struct NativeEntries {
const char* name;
Dart_NativeFunction function;
int argument_count;
} Entries[] = {SCENIC_NATIVE_LIST(REGISTER_FUNCTION)};
Dart_NativeFunction NativeLookup(Dart_Handle name,
int argument_count,
bool* auto_setup_scope) {
const char* function_name = nullptr;
Dart_Handle result = Dart_StringToCString(name, &function_name);
DART_CHECK_VALID(result);
assert(function_name != nullptr);
assert(auto_setup_scope != nullptr);
*auto_setup_scope = true;
size_t num_entries = arraysize(Entries);
for (size_t i = 0; i < num_entries; ++i) {
const struct NativeEntries& entry = Entries[i];
if (!strcmp(function_name, entry.name) &&
(entry.argument_count == argument_count)) {
return entry.function;
}
}
return nullptr;
}
const uint8_t* NativeSymbol(Dart_NativeFunction native_function) {
size_t num_entries = arraysize(Entries);
for (size_t i = 0; i < num_entries; ++i) {
const struct NativeEntries& entry = Entries[i];
if (entry.function == native_function) {
return reinterpret_cast<const uint8_t*>(entry.name);
}
}
return nullptr;
}
#define CHECK_INTEGER_ARGUMENT(args, num, result) \
{ \
Dart_Handle __status; \
__status = Dart_GetNativeIntegerArgument(args, num, result); \
if (Dart_IsError(__status)) { \
return; \
} \
}
#define CHECK_HANDLE_ARGUMENT(args, num, result) \
{ \
Dart_Handle __arg = Dart_GetNativeArgument(args, num); \
if (Dart_IsError(__arg)) { \
FXL_LOG(WARNING) << "GetNativeArgumentFailed: " << Dart_GetError(__arg); \
return; \
} \
Dart_Handle __err = Dart_Null(); \
*result = tonic::HandleTable::Current().Unwrap(__arg, &__err); \
if (Dart_IsError(__err)) { \
FXL_LOG(ERROR) << "Error unwrapping handle"; \
return; \
} \
if (*result == ZX_HANDLE_INVALID) { \
FXL_LOG(INFO) << "Invalid handle from unwrap"; \
return; \
} \
}
NativesDelegate::~NativesDelegate() {}
void Scenic_offerServiceProvider(Dart_NativeArguments args) {
intptr_t context = 0;
CHECK_INTEGER_ARGUMENT(args, 0, &context);
fxl::RefPtr<zircon::dart::Handle> handle =
zircon::dart::Handle::Unwrap(Dart_GetNativeArgument(args, 1));
if (!context || !handle)
return;
// TODO(jpoichet) Use lib/tonic to retrieve std::vector<std::string>
Dart_Handle list = Dart_GetNativeArgument(args, 2);
intptr_t list_length = 0;
Dart_Handle result = Dart_ListLength(list, &list_length);
if (Dart_IsError(result)) {
return;
}
std::vector<std::string> services;
services.resize(list_length);
for (intptr_t index = 0; index < list_length; ++index) {
Dart_Handle value = Dart_ListGetAt(list, index);
intptr_t length = 0;
result = Dart_StringLength(value, &length);
if (Dart_IsError(result)) {
return;
}
char* buffer = nullptr;
result =
Dart_StringToUTF8(value, reinterpret_cast<uint8_t**>(&buffer), &length);
if (Dart_IsError(result)) {
return;
}
buffer[length] = '\0';
services.at(index) = std::string(buffer);
}
NativesDelegate* delegate = reinterpret_cast<NativesDelegate*>(context);
fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> provider =
fidl::InterfaceHandle<fuchsia::sys::ServiceProvider>(
zx::channel(handle->ReleaseHandle()));
delegate->OfferServiceProvider(std::move(provider), std::move(services));
}
} // namespace mozart