From beb84ed2eadaaa0bae0c4447565680f79ec27560 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 12 Aug 2016 13:16:46 -0700 Subject: [PATCH] Move more code out of //flutter/sky/engine (flutter/engine#2918) * Move dart:mojo.internal to //flutter/lib/mojo To be parallel with the other built-in libraries. * Move DartRuntimeHooks into //flutter/lib/ui This code manipulates natives.dart, which is part of //flutter/lib/ui. --- engine/src/flutter/lib/mojo/BUILD.gn | 18 ++ .../flutter/lib/mojo/dart_mojo_internal.cc | 47 +++++ .../src/flutter/lib/mojo/dart_mojo_internal.h | 25 +++ engine/src/flutter/lib/ui/BUILD.gn | 7 +- .../src/flutter/lib/ui/dart_runtime_hooks.cc | 181 ++++++++++++++++++ .../src/flutter/lib/ui/dart_runtime_hooks.h | 30 +++ engine/src/flutter/lib/ui/natives.dart | 5 +- 7 files changed, 309 insertions(+), 4 deletions(-) create mode 100644 engine/src/flutter/lib/mojo/BUILD.gn create mode 100644 engine/src/flutter/lib/mojo/dart_mojo_internal.cc create mode 100644 engine/src/flutter/lib/mojo/dart_mojo_internal.h create mode 100644 engine/src/flutter/lib/ui/dart_runtime_hooks.cc create mode 100644 engine/src/flutter/lib/ui/dart_runtime_hooks.h diff --git a/engine/src/flutter/lib/mojo/BUILD.gn b/engine/src/flutter/lib/mojo/BUILD.gn new file mode 100644 index 00000000000..bfe16bfbde0 --- /dev/null +++ b/engine/src/flutter/lib/mojo/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright 2016 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. + +source_set("mojo") { + sources = [ + "dart_mojo_internal.cc", + "dart_mojo_internal.h", + ] + + deps = [ + "//dart/runtime:libdart", + "//lib/ftl", + "//lib/tonic", + "//mojo/public/cpp/system", + "//mojo/public/platform/dart:mojo_internal_impl", + ] +} diff --git a/engine/src/flutter/lib/mojo/dart_mojo_internal.cc b/engine/src/flutter/lib/mojo/dart_mojo_internal.cc new file mode 100644 index 00000000000..1206a586caf --- /dev/null +++ b/engine/src/flutter/lib/mojo/dart_mojo_internal.cc @@ -0,0 +1,47 @@ +// Copyright 2014 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 "flutter/lib/mojo/dart_mojo_internal.h" + +#include "dart/runtime/include/dart_api.h" +#include "lib/ftl/logging.h" +#include "lib/tonic/converter/dart_converter.h" +#include "lib/tonic/logging/dart_error.h" +#include "mojo/public/platform/dart/mojo_natives.h" + +using tonic::LogIfError; +using tonic::ToDart; + +namespace blink { +namespace { + +MojoHandle g_handle_watcher_producer_handle = MOJO_HANDLE_INVALID; + +void SetHandleWatcherControlHandle(Dart_Handle mojo_internal) { + FTL_CHECK(g_handle_watcher_producer_handle != MOJO_HANDLE_INVALID); + Dart_Handle handle_watcher_type = + Dart_GetType(mojo_internal, ToDart("MojoHandleWatcher"), 0, nullptr); + Dart_Handle field_name = ToDart("mojoControlHandle"); + Dart_Handle control_port_value = ToDart(g_handle_watcher_producer_handle); + Dart_Handle result = + Dart_SetField(handle_watcher_type, field_name, control_port_value); + FTL_CHECK(!LogIfError(result)); +} + +} // namespace + +void DartMojoInternal::SetHandleWatcherProducerHandle(MojoHandle handle) { + FTL_CHECK(g_handle_watcher_producer_handle == MOJO_HANDLE_INVALID); + g_handle_watcher_producer_handle = handle; +} + +void DartMojoInternal::InitForIsolate() { + Dart_Handle mojo_internal = Dart_LookupLibrary(ToDart("dart:mojo.internal")); + DART_CHECK_VALID(Dart_SetNativeResolver(mojo_internal, + mojo::dart::MojoNativeLookup, + mojo::dart::MojoNativeSymbol)); + SetHandleWatcherControlHandle(mojo_internal); +} + +} // namespace blink diff --git a/engine/src/flutter/lib/mojo/dart_mojo_internal.h b/engine/src/flutter/lib/mojo/dart_mojo_internal.h new file mode 100644 index 00000000000..8cc2e82b635 --- /dev/null +++ b/engine/src/flutter/lib/mojo/dart_mojo_internal.h @@ -0,0 +1,25 @@ +// Copyright 2014 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. + +#ifndef FLUTTER_LIB_MOJO_DART_MOJO_INTERNAL_H_ +#define FLUTTER_LIB_MOJO_DART_MOJO_INTERNAL_H_ + +#include "lib/ftl/macros.h" +#include "mojo/public/cpp/system/handle.h" + +namespace blink { + +class DartMojoInternal { + public: + static void InitForIsolate(); + + static void SetHandleWatcherProducerHandle(MojoHandle handle); + + private: + FTL_DISALLOW_IMPLICIT_CONSTRUCTORS(DartMojoInternal); +}; + +} // namespace blink + +#endif // FLUTTER_LIB_MOJO_DART_MOJO_INTERNAL_H_ diff --git a/engine/src/flutter/lib/ui/BUILD.gn b/engine/src/flutter/lib/ui/BUILD.gn index fe7e7e88e80..b6806dd6b11 100644 --- a/engine/src/flutter/lib/ui/BUILD.gn +++ b/engine/src/flutter/lib/ui/BUILD.gn @@ -8,18 +8,20 @@ source_set("ui") { "compositing/scene_builder.h", "compositing/scene.cc", "compositing/scene.h", + "dart_runtime_hooks.cc", + "dart_runtime_hooks.h", "painting/canvas.cc", "painting/canvas.h", "painting/gradient.cc", "painting/gradient.h", - "painting/image.cc", "painting/image_decoding.cc", "painting/image_decoding.h", "painting/image_filter.cc", "painting/image_filter.h", - "painting/image.h", "painting/image_shader.cc", "painting/image_shader.h", + "painting/image.cc", + "painting/image.h", "painting/mask_filter.cc", "painting/mask_filter.h", "painting/matrix.cc", @@ -41,6 +43,7 @@ source_set("ui") { ] deps = [ + "//dart/runtime/bin:embedded_dart_io", "//flutter/common", "//flutter/flow", "//flutter/glue", diff --git a/engine/src/flutter/lib/ui/dart_runtime_hooks.cc b/engine/src/flutter/lib/ui/dart_runtime_hooks.cc new file mode 100644 index 00000000000..0b0c822c956 --- /dev/null +++ b/engine/src/flutter/lib/ui/dart_runtime_hooks.cc @@ -0,0 +1,181 @@ +// Copyright 2014 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 "flutter/lib/ui/dart_runtime_hooks.h" + +#include +#include +#include + +#include "dart/runtime/bin/embedded_dart_io.h" +#include "dart/runtime/include/dart_api.h" +#include "dart/runtime/include/dart_tools_api.h" +#include "lib/ftl/logging.h" +#include "lib/tonic/converter/dart_converter.h" +#include "lib/tonic/dart_library_natives.h" +#include "lib/tonic/dart_microtask_queue.h" +#include "lib/tonic/dart_state.h" +#include "lib/tonic/logging/dart_error.h" +#include "lib/tonic/logging/dart_invoke.h" +#include "lib/tonic/scopes/dart_api_scope.h" +#include "lib/tonic/scopes/dart_isolate_scope.h" + +#if defined(OS_ANDROID) +#include +#endif + +#if __APPLE__ +extern "C" { +// Cannot import the syslog.h header directly because of macro collision +extern void syslog(int, const char*, ...); +} +#endif + +using tonic::LogIfError; +using tonic::ToDart; + +namespace blink { + +#define REGISTER_FUNCTION(name, count) {"" #name, name, count, true}, +#define DECLARE_FUNCTION(name, count) \ + extern void name(Dart_NativeArguments args); + +// Lists the native functions implementing basic functionality in +// the Mojo embedder dart, such as printing, and file I/O. +#define BUILTIN_NATIVE_LIST(V) \ + V(Logger_PrintString, 1) \ + V(ScheduleMicrotask, 1) + +BUILTIN_NATIVE_LIST(DECLARE_FUNCTION); + +void DartRuntimeHooks::RegisterNatives(tonic::DartLibraryNatives* natives) { + natives->Register({BUILTIN_NATIVE_LIST(REGISTER_FUNCTION)}); +} + +static Dart_Handle GetClosure(Dart_Handle builtin_library, const char* name) { + Dart_Handle getter_name = ToDart(name); + Dart_Handle closure = Dart_Invoke(builtin_library, getter_name, 0, nullptr); + DART_CHECK_VALID(closure); + return closure; +} + +static void InitDartInternal(Dart_Handle builtin_library, + DartRuntimeHooks::IsolateType isolate_type) { + Dart_Handle print = GetClosure(builtin_library, "_getPrintClosure"); + + Dart_Handle internal_library = Dart_LookupLibrary(ToDart("dart:_internal")); + + DART_CHECK_VALID( + Dart_SetField(internal_library, ToDart("_printClosure"), print)); + + if (isolate_type == DartRuntimeHooks::MainIsolate) { + // Call |_setupHooks| to configure |VMLibraryHooks|. + Dart_Handle method_name = Dart_NewStringFromCString("_setupHooks"); + DART_CHECK_VALID(Dart_Invoke(builtin_library, method_name, 0, NULL)) + + // Call |_setupHooks| to configure |VMLibraryHooks|. + Dart_Handle isolate_lib = Dart_LookupLibrary(ToDart("dart:isolate")); + DART_CHECK_VALID(isolate_lib); + DART_CHECK_VALID(Dart_Invoke(isolate_lib, method_name, 0, NULL)); + } else { + FTL_CHECK(isolate_type == DartRuntimeHooks::SecondaryIsolate); + Dart_Handle io_lib = Dart_LookupLibrary(ToDart("dart:io")); + DART_CHECK_VALID(io_lib); + Dart_Handle setup_hooks = Dart_NewStringFromCString("_setupHooks"); + DART_CHECK_VALID(Dart_Invoke(io_lib, setup_hooks, 0, NULL)); + Dart_Handle isolate_lib = Dart_LookupLibrary(ToDart("dart:isolate")); + DART_CHECK_VALID(isolate_lib); + DART_CHECK_VALID(Dart_Invoke(isolate_lib, setup_hooks, 0, NULL)); + } +} + +static void InitDartCore(Dart_Handle builtin, const std::string& script_uri) { + DART_CHECK_VALID( + Dart_SetField(builtin, ToDart("_baseURL"), ToDart(script_uri))); + Dart_Handle get_base_url = GetClosure(builtin, "_getGetBaseURLClosure"); + Dart_Handle core_library = Dart_LookupLibrary(ToDart("dart:core")); + DART_CHECK_VALID( + Dart_SetField(core_library, ToDart("_uriBaseClosure"), get_base_url)); +} + +static void InitDartAsync(Dart_Handle builtin_library, + DartRuntimeHooks::IsolateType isolate_type) { + Dart_Handle schedule_microtask; + if (isolate_type == DartRuntimeHooks::MainIsolate) { + schedule_microtask = + GetClosure(builtin_library, "_getScheduleMicrotaskClosure"); + } else { + FTL_CHECK(isolate_type == DartRuntimeHooks::SecondaryIsolate); + Dart_Handle isolate_lib = Dart_LookupLibrary(ToDart("dart:isolate")); + Dart_Handle method_name = + Dart_NewStringFromCString("_getIsolateScheduleImmediateClosure"); + schedule_microtask = Dart_Invoke(isolate_lib, method_name, 0, NULL); + } + Dart_Handle async_library = Dart_LookupLibrary(ToDart("dart:async")); + Dart_Handle set_schedule_microtask = ToDart("_setScheduleImmediateClosure"); + DART_CHECK_VALID(Dart_Invoke(async_library, set_schedule_microtask, 1, + &schedule_microtask)); +} + +static void InitDartIo(const std::string& script_uri) { + if (!script_uri.empty()) { + Dart_Handle io_lib = Dart_LookupLibrary(ToDart("dart:io")); + DART_CHECK_VALID(io_lib); + Dart_Handle platform_type = + Dart_GetType(io_lib, ToDart("_Platform"), 0, nullptr); + DART_CHECK_VALID(platform_type); + DART_CHECK_VALID(Dart_SetField(platform_type, ToDart("_nativeScript"), + ToDart(script_uri))); + } +} + +void DartRuntimeHooks::Install(IsolateType isolate_type, + const std::string& script_uri) { + Dart_Handle builtin = Dart_LookupLibrary(ToDart("dart:ui")); + DART_CHECK_VALID(builtin); + InitDartInternal(builtin, isolate_type); + InitDartCore(builtin, script_uri); + InitDartAsync(builtin, isolate_type); + InitDartIo(script_uri); +} + +// Implementation of native functions which are used for some +// test/debug functionality in standalone dart mode. +void Logger_PrintString(Dart_NativeArguments args) { + intptr_t length = 0; + uint8_t* chars = nullptr; + Dart_Handle str = Dart_GetNativeArgument(args, 0); + Dart_Handle result = Dart_StringToUTF8(str, &chars, &length); + if (Dart_IsError(result)) { + Dart_PropagateError(result); + } else { + // Uses fwrite to support printing NUL bytes. + fwrite(chars, 1, length, stdout); + fputs("\n", stdout); + fflush(stdout); +#if defined(OS_ANDROID) + // In addition to writing to the stdout, write to the logcat so that the + // message is discoverable when running on an unrooted device. + __android_log_print(ANDROID_LOG_INFO, "flutter", "%.*s", (int)length, + chars); +#elif __APPLE__ + syslog(1 /* LOG_ALERT */, "%.*s", (int)length, chars); +#endif + } + if (dart::bin::ShouldCaptureStdout()) { + // For now we report print output on the Stdout stream. + uint8_t newline[] = {'\n'}; + Dart_ServiceSendDataEvent("Stdout", "WriteEvent", chars, length); + Dart_ServiceSendDataEvent("Stdout", "WriteEvent", newline, sizeof(newline)); + } +} + +void ScheduleMicrotask(Dart_NativeArguments args) { + Dart_Handle closure = Dart_GetNativeArgument(args, 0); + if (LogIfError(closure) || !Dart_IsClosure(closure)) + return; + tonic::DartMicrotaskQueue::ScheduleMicrotask(closure); +} + +} // namespace blink diff --git a/engine/src/flutter/lib/ui/dart_runtime_hooks.h b/engine/src/flutter/lib/ui/dart_runtime_hooks.h new file mode 100644 index 00000000000..e9522a8bdf3 --- /dev/null +++ b/engine/src/flutter/lib/ui/dart_runtime_hooks.h @@ -0,0 +1,30 @@ +// Copyright 2014 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. + +#ifndef FLUTTER_LIB_UI_DART_RUNTIME_HOOKS_H_ +#define FLUTTER_LIB_UI_DART_RUNTIME_HOOKS_H_ + +#include "dart/runtime/include/dart_api.h" +#include "lib/tonic/dart_library_natives.h" +#include "lib/ftl/macros.h" + +namespace blink { + +class DartRuntimeHooks { + public: + enum IsolateType { + MainIsolate, + SecondaryIsolate, + }; + + static void Install(IsolateType isolate_type, const std::string& script_uri); + static void RegisterNatives(tonic::DartLibraryNatives* natives); + + private: + FTL_DISALLOW_IMPLICIT_CONSTRUCTORS(DartRuntimeHooks); +}; + +} // namespace blink + +#endif // FLUTTER_LIB_UI_DART_RUNTIME_HOOKS_H_ diff --git a/engine/src/flutter/lib/ui/natives.dart b/engine/src/flutter/lib/ui/natives.dart index 528dcd6892d..7b9b19dc160 100644 --- a/engine/src/flutter/lib/ui/natives.dart +++ b/engine/src/flutter/lib/ui/natives.dart @@ -20,8 +20,9 @@ void _setupHooks() { } void _scheduleMicrotask(void callback()) native "ScheduleMicrotask"; -String _getBaseURLString() native "GetBaseURLString"; -Uri _getBaseURL() => Uri.parse(_getBaseURLString()); + +String _baseURL; +Uri _getBaseURL() => Uri.parse(_baseURL); // Required for gen_snapshot to work correctly. int _isolateId;