From cee7fef78cfbdf05edf8e10bbdc21e5b02ea34b8 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 11 Aug 2016 10:23:17 -0700 Subject: [PATCH] Simplify Dart application startup (#2910) There are now three ways to start Dart applications: 1) From a precompiled snapshot 2) From a snapshot 3) From source When loading from source, we no longer use the complex data pipe / dependency catcher mechanism. Instead, we just load the source synchronously from the file system. This is appropriate because running from source is used only during development and not during production. The previous design was built assuming we would want to run from source over the network, which meant we needed to be able to load source asynchronously over a high latency channel. --- DEPS | 2 +- sky/engine/core/script/dart_controller.cc | 120 ++++---- sky/engine/core/script/dart_controller.h | 12 +- sky/engine/core/script/dart_init.cc | 20 +- sky/engine/core/script/dart_init.h | 3 - sky/engine/public/sky/sky_view.cc | 17 +- sky/engine/public/sky/sky_view.h | 6 +- sky/shell/ui/engine.cc | 86 ++---- sky/shell/ui/engine.h | 22 +- snapshotter/main.cc | 11 +- tonic/BUILD.gn | 18 +- tonic/dart_dependency_catcher.cc | 24 -- tonic/dart_dependency_catcher.h | 39 --- tonic/dart_isolate_reloader.cc | 315 -------------------- tonic/dart_isolate_reloader.h | 71 ----- tonic/dart_library_loader.cc | 335 ---------------------- tonic/dart_library_loader.h | 86 ------ tonic/dart_library_provider.cc | 12 - tonic/dart_library_provider.h | 32 --- tonic/dart_library_provider_files.cc | 159 ---------- tonic/dart_library_provider_files.h | 42 --- tonic/dart_snapshot_loader.cc | 46 --- tonic/dart_snapshot_loader.h | 35 --- tonic/dart_state.cc | 6 +- tonic/dart_state.h | 21 -- 25 files changed, 106 insertions(+), 1434 deletions(-) delete mode 100644 tonic/dart_dependency_catcher.cc delete mode 100644 tonic/dart_dependency_catcher.h delete mode 100644 tonic/dart_isolate_reloader.cc delete mode 100644 tonic/dart_isolate_reloader.h delete mode 100644 tonic/dart_library_loader.cc delete mode 100644 tonic/dart_library_loader.h delete mode 100644 tonic/dart_library_provider.cc delete mode 100644 tonic/dart_library_provider.h delete mode 100644 tonic/dart_library_provider_files.cc delete mode 100644 tonic/dart_library_provider_files.h delete mode 100644 tonic/dart_snapshot_loader.cc delete mode 100644 tonic/dart_snapshot_loader.h diff --git a/DEPS b/DEPS index 58e8f4c09be..629f439531c 100644 --- a/DEPS +++ b/DEPS @@ -55,7 +55,7 @@ deps = { Var('fuchsia_git') + '/ftl' + '@' + '0bb3a02301c8a88b494e58c6636fa509525adaa8', 'src/lib/tonic': - Var('fuchsia_git') + '/tonic' + '@' + '8e0776dc4aa1c7fab21b742279ef90527c59b216', + Var('fuchsia_git') + '/tonic' + '@' + '66fc8a71ae54c628537e7f4b2e8bf9304788c19d', 'src/third_party/gtest': Var('fuchsia_git') + '/third_party/gtest' + '@' + 'c00f82917331efbbd27124b537e4ccc915a02b72', diff --git a/sky/engine/core/script/dart_controller.cc b/sky/engine/core/script/dart_controller.cc index 94af2119658..beb2699f07f 100644 --- a/sky/engine/core/script/dart_controller.cc +++ b/sky/engine/core/script/dart_controller.cc @@ -4,22 +4,10 @@ #include "flutter/sky/engine/core/script/dart_controller.h" +#include + #include "dart/runtime/include/dart_tools_api.h" -#include "flutter/tonic/dart_debugger.h" -#include "flutter/tonic/dart_dependency_catcher.h" -#include "flutter/tonic/dart_io.h" -#include "flutter/tonic/dart_library_loader.h" -#include "flutter/tonic/dart_snapshot_loader.h" -#include "flutter/tonic/dart_state.h" #include "flutter/glue/trace_event.h" -#include "lib/tonic/dart_class_library.h" -#include "lib/tonic/dart_message_handler.h" -#include "lib/tonic/dart_wrappable.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" -#include "mojo/public/cpp/system/data_pipe.h" #include "flutter/sky/engine/bindings/dart_mojo_internal.h" #include "flutter/sky/engine/bindings/dart_runtime_hooks.h" #include "flutter/sky/engine/bindings/dart_ui.h" @@ -29,6 +17,20 @@ #include "flutter/sky/engine/public/platform/Platform.h" #include "flutter/sky/engine/public/platform/sky_settings.h" #include "flutter/sky/engine/wtf/MakeUnique.h" +#include "flutter/tonic/dart_debugger.h" +#include "flutter/tonic/dart_io.h" +#include "flutter/tonic/dart_state.h" +#include "lib/ftl/files/directory.h" +#include "lib/ftl/files/path.h" +#include "lib/tonic/dart_class_library.h" +#include "lib/tonic/dart_message_handler.h" +#include "lib/tonic/dart_wrappable.h" +#include "lib/tonic/file_loader/file_loader.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" +#include "mojo/public/cpp/system/data_pipe.h" #ifdef OS_ANDROID #include "flutter/lib/jni/dart_jni.h" @@ -38,6 +40,16 @@ using tonic::LogIfError; using tonic::ToDart; namespace blink { +namespace { + +// TODO(abarth): Consider adding this to //lib/ftl. +std::string ResolvePath(std::string path) { + if (!path.empty() && path[0] == '/') + return path; + return files::SimplifyPath(files::GetCurrentDirectory() + "/" + path); +} + +} // namespace DartController::DartController() : ui_dart_state_(nullptr) {} @@ -53,6 +65,9 @@ DartController::~DartController() { } bool DartController::SendStartMessage(Dart_Handle root_library) { + if (LogIfError(root_library)) + return true; + { // Temporarily exit the isolate while we make it runnable. Dart_Isolate isolate = dart_state()->isolate(); @@ -93,67 +108,30 @@ bool DartController::SendStartMessage(Dart_Handle root_library) { return LogIfError(result); } -void DartController::DidLoadMainLibrary(std::string name) { - FTL_DCHECK(Dart_CurrentIsolate() == dart_state()->isolate()); - tonic::DartApiScope dart_api_scope; - - FTL_CHECK(!LogIfError(Dart_FinalizeLoading(true))); - - Dart_Handle library = Dart_LookupLibrary(ToDart(name)); - if (LogIfError(library)) - exit(1); - if (SendStartMessage(library)) - exit(1); -} - -void DartController::DidLoadSnapshot() { - TRACE_EVENT0("flutter", "DartController::DidLoadSnapshot"); - - FTL_DCHECK(Dart_CurrentIsolate() == nullptr); - snapshot_loader_ = nullptr; - - Dart_Isolate isolate = dart_state()->isolate(); - tonic::DartIsolateScope isolate_scope(isolate); - tonic::DartApiScope dart_api_scope; - Dart_Handle library = Dart_RootLibrary(); - if (LogIfError(library)) - exit(1); - if (SendStartMessage(library)) - exit(1); -} - void DartController::RunFromPrecompiledSnapshot() { - DidLoadSnapshot(); + TRACE_EVENT0("flutter", "DartController::RunFromPrecompiledSnapshot"); + FTL_DCHECK(Dart_CurrentIsolate() == nullptr); + tonic::DartState::Scope scope(dart_state()); + if (SendStartMessage(Dart_RootLibrary())) + exit(1); } -void DartController::RunFromSnapshot( - mojo::ScopedDataPipeConsumerHandle snapshot) { - snapshot_loader_ = WTF::MakeUnique(dart_state()); - snapshot_loader_->LoadSnapshot(snapshot.Pass(), - [this]() { DidLoadSnapshot(); }); -} - -void DartController::RunFromSnapshotBuffer(const uint8_t* buffer, size_t size) { - DartState::Scope scope(dart_state()); +void DartController::RunFromSnapshot(const uint8_t* buffer, size_t size) { + tonic::DartState::Scope scope(dart_state()); LogIfError(Dart_LoadScriptFromSnapshot(buffer, size)); - Dart_Handle library = Dart_RootLibrary(); - if (LogIfError(library)) - exit(1); - if (SendStartMessage(library)) + if (SendStartMessage(Dart_RootLibrary())) exit(1); } -void DartController::RunFromLibrary(std::string name, - DartLibraryProvider* library_provider) { - DartState::Scope scope(dart_state()); - - DartLibraryLoader& loader = dart_state()->library_loader(); - loader.set_library_provider(library_provider); - - DartDependencyCatcher dependency_catcher(loader); - loader.LoadScript(name); - loader.WaitForDependencies(dependency_catcher.dependencies(), - [this, name]() { DidLoadMainLibrary(name); }); +void DartController::RunFromSource(const std::string& main, + const std::string& packages) { + tonic::DartState::Scope scope(dart_state()); + tonic::FileLoader& loader = dart_state()->file_loader(); + if (!packages.empty() && !loader.LoadPackagesMap(ResolvePath(packages))) + FTL_LOG(WARNING) << "Failed to load package map: " << packages; + LogIfError(loader.LoadScript(main)); + if (SendStartMessage(Dart_RootLibrary())) + exit(1); } void DartController::CreateIsolateFor(std::unique_ptr state) { @@ -164,15 +142,15 @@ void DartController::CreateIsolateFor(std::unique_ptr state) { nullptr, static_cast(state.get()), &error); FTL_CHECK(isolate) << error; ui_dart_state_ = state.release(); - auto& message_handler = dart_state()->message_handler(); FTL_DCHECK(Platform::current()); - message_handler.Initialize( + dart_state()->message_handler().Initialize( ftl::RefPtr(Platform::current()->GetUITaskRunner())); Dart_SetShouldPauseOnStart(SkySettings::Get().start_paused); ui_dart_state_->SetIsolate(isolate); - FTL_CHECK(!LogIfError(Dart_SetLibraryTagHandler(DartLibraryTagHandler))); + FTL_CHECK(!LogIfError( + Dart_SetLibraryTagHandler(tonic::DartState::HandleLibraryTag))); { tonic::DartApiScope dart_api_scope; diff --git a/sky/engine/core/script/dart_controller.h b/sky/engine/core/script/dart_controller.h index 2913955959e..a7b60bd7f9d 100644 --- a/sky/engine/core/script/dart_controller.h +++ b/sky/engine/core/script/dart_controller.h @@ -13,8 +13,6 @@ namespace blink { class UIDartState; -class DartLibraryProvider; -class DartSnapshotLoader; class DartController { public: @@ -23,27 +21,21 @@ class DartController { static void InitVM(); - void RunFromLibrary(std::string name, DartLibraryProvider* library_provider); void RunFromPrecompiledSnapshot(); - void RunFromSnapshot(mojo::ScopedDataPipeConsumerHandle snapshot); - void RunFromSnapshotBuffer(const uint8_t* buffer, size_t size); + void RunFromSnapshot(const uint8_t* buffer, size_t size); + void RunFromSource(const std::string& main, const std::string& packages); void CreateIsolateFor(std::unique_ptr ui_dart_state); - void Shutdown(); UIDartState* dart_state() const { return ui_dart_state_; } private: - void DidLoadMainLibrary(std::string url); - void DidLoadSnapshot(); bool SendStartMessage(Dart_Handle root_library); // The DartState associated with the main isolate. This will be deleted // during isolate shutdown. UIDartState* ui_dart_state_; - std::unique_ptr snapshot_loader_; - FTL_DISALLOW_COPY_AND_ASSIGN(DartController); }; } diff --git a/sky/engine/core/script/dart_init.cc b/sky/engine/core/script/dart_init.cc index 7a6a37a74b9..41d80a8de15 100644 --- a/sky/engine/core/script/dart_init.cc +++ b/sky/engine/core/script/dart_init.cc @@ -16,10 +16,7 @@ #include "dart/runtime/include/dart_mirrors_api.h" #include "flutter/assets/zip_asset_store.h" #include "flutter/tonic/dart_debugger.h" -#include "flutter/tonic/dart_dependency_catcher.h" #include "flutter/tonic/dart_io.h" -#include "flutter/tonic/dart_library_loader.h" -#include "flutter/tonic/dart_snapshot_loader.h" #include "flutter/tonic/dart_state.h" #include "flutter/glue/trace_event.h" #include "lib/ftl/files/eintr_wrapper.h" @@ -70,12 +67,6 @@ namespace blink { const char kSnapshotAssetKey[] = "snapshot_blob.bin"; -Dart_Handle DartLibraryTagHandler(Dart_LibraryTag tag, - Dart_Handle library, - Dart_Handle url) { - return DartLibraryLoader::HandleLibraryTag(tag, library, url); -} - namespace { static const char* kDartProfilingArgs[] = { @@ -192,7 +183,8 @@ Dart_Isolate ServiceIsolateCreateCallback(const char* script_uri, FTL_CHECK(isolate) << error; dart_state->SetIsolate(isolate); FTL_CHECK(Dart_IsServiceIsolate(isolate)); - FTL_CHECK(!LogIfError(Dart_SetLibraryTagHandler(DartLibraryTagHandler))); + FTL_CHECK(!LogIfError( + Dart_SetLibraryTagHandler(tonic::DartState::HandleLibraryTag))); { tonic::DartApiScope dart_api_scope; DartIO::InitForIsolate(); @@ -205,8 +197,8 @@ Dart_Isolate ServiceIsolateCreateCallback(const char* script_uri, const intptr_t port = settings.observatory_port; const bool disable_websocket_origin_check = false; const bool service_isolate_booted = DartServiceIsolate::Startup( - ip, port, DartLibraryTagHandler, IsRunningPrecompiledCode(), - disable_websocket_origin_check, error); + ip, port, tonic::DartState::HandleLibraryTag, + IsRunningPrecompiledCode(), disable_websocket_origin_check, error); FTL_CHECK(service_isolate_booted) << error; } @@ -260,8 +252,8 @@ Dart_Isolate IsolateCreateCallback(const char* script_uri, nullptr, dart_state, error); FTL_CHECK(isolate) << error; dart_state->SetIsolate(isolate); - - FTL_CHECK(!LogIfError(Dart_SetLibraryTagHandler(DartLibraryTagHandler))); + FTL_CHECK(!LogIfError( + Dart_SetLibraryTagHandler(tonic::DartState::HandleLibraryTag))); { tonic::DartApiScope dart_api_scope; diff --git a/sky/engine/core/script/dart_init.h b/sky/engine/core/script/dart_init.h index fee3cdc3ef0..d8c5eb9044d 100644 --- a/sky/engine/core/script/dart_init.h +++ b/sky/engine/core/script/dart_init.h @@ -67,9 +67,6 @@ void SetServiceIsolateHook(ServiceIsolateHook hook); void SetRegisterNativeServiceProtocolExtensionHook( RegisterNativeServiceProtocolExtensionHook hook); -Dart_Handle DartLibraryTagHandler(Dart_LibraryTag tag, - Dart_Handle library, - Dart_Handle url); } // namespace blink #endif // SKY_ENGINE_CORE_SCRIPT_DART_INIT_H_ diff --git a/sky/engine/public/sky/sky_view.cc b/sky/engine/public/sky/sky_view.cc index c67845ae3e2..3176e62b001 100644 --- a/sky/engine/public/sky/sky_view.cc +++ b/sky/engine/public/sky/sky_view.cc @@ -18,8 +18,7 @@ std::unique_ptr SkyView::Create(SkyViewClient* client) { return std::unique_ptr(new SkyView(client)); } -SkyView::SkyView(SkyViewClient* client) - : client_(client) {} +SkyView::SkyView(SkyViewClient* client) : client_(client) {} SkyView::~SkyView() {} @@ -67,19 +66,6 @@ void SkyView::CreateView(const std::string& script_uri) { GetWindow()->UpdateLocale(language_code_, country_code_); } -void SkyView::RunFromLibrary(const std::string& name, - DartLibraryProvider* library_provider) { - dart_controller_->RunFromLibrary(name, library_provider); -} - -void SkyView::RunFromPrecompiledSnapshot() { - dart_controller_->RunFromPrecompiledSnapshot(); -} - -void SkyView::RunFromSnapshot(mojo::ScopedDataPipeConsumerHandle snapshot) { - dart_controller_->RunFromSnapshot(snapshot.Pass()); -} - void SkyView::BeginFrame(ftl::TimePoint frame_time) { GetWindow()->BeginFrame(frame_time); } @@ -123,5 +109,4 @@ Dart_Port SkyView::GetMainPort() { return dart_controller_->dart_state()->main_port(); } - } // namespace blink diff --git a/sky/engine/public/sky/sky_view.h b/sky/engine/public/sky/sky_view.h index 454a3d1501c..54b35217659 100644 --- a/sky/engine/public/sky/sky_view.h +++ b/sky/engine/public/sky/sky_view.h @@ -43,11 +43,7 @@ class SkyView : public WindowClient, public IsolateClient { void BeginFrame(ftl::TimePoint frame_time); void CreateView(const std::string& script_uri); - - void RunFromLibrary(const std::string& name, - DartLibraryProvider* library_provider); - void RunFromPrecompiledSnapshot(); - void RunFromSnapshot(mojo::ScopedDataPipeConsumerHandle snapshot); + DartController* dart_controller() const { return dart_controller_.get(); } void HandlePointerPacket(const pointer::PointerPacketPtr& packet); diff --git a/sky/shell/ui/engine.cc b/sky/shell/ui/engine.cc index 45e496b75f8..e219a48630d 100644 --- a/sky/shell/ui/engine.cc +++ b/sky/shell/ui/engine.cc @@ -6,14 +6,16 @@ #include +#include + #include "flutter/assets/directory_asset_bundle.h" #include "flutter/assets/zip_asset_bundle.h" -#include "flutter/tonic/dart_library_provider_files.h" #include "flutter/glue/movable_wrapper.h" #include "flutter/glue/trace_event.h" #include "lib/ftl/files/path.h" #include "mojo/public/cpp/application/connect.h" #include "flutter/sky/engine/bindings/mojo_services.h" +#include "flutter/sky/engine/core/script/dart_controller.h" #include "flutter/sky/engine/core/script/dart_init.h" #include "flutter/sky/engine/core/script/ui_dart_state.h" #include "flutter/sky/engine/public/platform/Platform.h" @@ -83,25 +85,20 @@ void Engine::BeginFrame(ftl::TimePoint frame_time) { void Engine::RunFromSource(const std::string& main, const std::string& packages, - const std::string& assets_directory) { + const std::string& bundle) { TRACE_EVENT0("flutter", "Engine::RunFromSource"); - // Assets. - ConfigureDirectoryAssetBundle(assets_directory); - // .packages. std::string packages_path = packages; if (packages_path.empty()) packages_path = FindPackagesPath(main); - DartLibraryProviderFiles* provider = new DartLibraryProviderFiles(); - dart_library_provider_.reset(provider); - if (!packages_path.empty()) - provider->LoadPackagesMap(packages_path); - RunFromLibrary(main); + if (!bundle.empty()) + ConfigureDirectoryAssetBundle(bundle); + ConfigureView(main); + sky_view_->dart_controller()->RunFromSource(main, packages_path); } Dart_Port Engine::GetUIIsolateMainPort() { - if (!sky_view_) { + if (!sky_view_) return ILLEGAL_PORT; - } return sky_view_->GetMainPort(); } @@ -183,34 +180,24 @@ void Engine::OnPointerPacket(pointer::PointerPacketPtr packet) { sky_view_->HandlePointerPacket(packet); } -void Engine::RunFromLibrary(const std::string& name) { - TRACE_EVENT0("flutter", "Engine::RunFromLibrary"); - sky_view_ = blink::SkyView::Create(this); - sky_view_->CreateView(name); - sky_view_->RunFromLibrary(name, dart_library_provider_.get()); - sky_view_->SetViewportMetrics(viewport_metrics_); - sky_view_->SetLocale(language_code_, country_code_); - if (!initial_route_.empty()) - sky_view_->PushRoute(initial_route_); -} - void Engine::RunFromSnapshotStream( const std::string& script_uri, mojo::ScopedDataPipeConsumerHandle snapshot) { TRACE_EVENT0("flutter", "Engine::RunFromSnapshotStream"); - sky_view_ = blink::SkyView::Create(this); - sky_view_->CreateView(script_uri); - sky_view_->RunFromSnapshot(snapshot.Pass()); - sky_view_->SetViewportMetrics(viewport_metrics_); - sky_view_->SetLocale(language_code_, country_code_); - if (!initial_route_.empty()) - sky_view_->PushRoute(initial_route_); + ConfigureView(script_uri); + snapshot_drainer_.reset(new glue::DrainDataPipeJob( + std::move(snapshot), [this](std::vector snapshot) { + FTL_DCHECK(sky_view_); + FTL_DCHECK(sky_view_->dart_controller()); + sky_view_->dart_controller()->RunFromSnapshot( + reinterpret_cast(snapshot.data()), snapshot.size()); + })); } -void Engine::ConfigureZipAssetBundle(const mojo::String& path) { +void Engine::ConfigureZipAssetBundle(const std::string& path) { asset_store_ = ftl::MakeRefCounted( - path.get(), ftl::RefPtr( - blink::Platform::current()->GetIOTaskRunner())); + path, ftl::RefPtr( + blink::Platform::current()->GetIOTaskRunner())); new blink::ZipAssetBundle(mojo::GetProxy(&root_bundle_), asset_store_); } @@ -221,43 +208,32 @@ void Engine::ConfigureDirectoryAssetBundle(const std::string& path) { blink::Platform::current()->GetIOTaskRunner())); } -void Engine::RunFromPrecompiledSnapshot(const mojo::String& bundle_path) { - TRACE_EVENT0("flutter", "Engine::RunFromPrecompiledSnapshot"); - - ConfigureZipAssetBundle(bundle_path); - +void Engine::ConfigureView(const std::string& script_uri) { + snapshot_drainer_.reset(); sky_view_ = blink::SkyView::Create(this); - sky_view_->CreateView("http://localhost"); - sky_view_->RunFromPrecompiledSnapshot(); + sky_view_->CreateView(std::move(script_uri)); sky_view_->SetViewportMetrics(viewport_metrics_); sky_view_->SetLocale(language_code_, country_code_); if (!initial_route_.empty()) sky_view_->PushRoute(initial_route_); } +void Engine::RunFromPrecompiledSnapshot(const mojo::String& bundle_path) { + TRACE_EVENT0("flutter", "Engine::RunFromPrecompiledSnapshot"); + ConfigureZipAssetBundle(bundle_path.get()); + ConfigureView("http://localhost"); + sky_view_->dart_controller()->RunFromPrecompiledSnapshot(); +} + void Engine::RunFromFile(const mojo::String& main, const mojo::String& packages, const mojo::String& bundle) { - TRACE_EVENT0("flutter", "Engine::RunFromFile"); - std::string main_dart(main); - if (bundle.size() != 0) { - // The specification of an FLX bundle is optional. - ConfigureZipAssetBundle(bundle); - } - std::string packages_path = packages; - if (packages_path.empty()) - packages_path = FindPackagesPath(main_dart); - DartLibraryProviderFiles* provider = new DartLibraryProviderFiles(); - dart_library_provider_.reset(provider); - if (!packages_path.empty()) - provider->LoadPackagesMap(packages_path); - RunFromLibrary(main_dart); + RunFromSource(main, packages, bundle); } void Engine::RunFromBundle(const mojo::String& script_uri, const mojo::String& path) { TRACE_EVENT0("flutter", "Engine::RunFromBundle"); - ConfigureZipAssetBundle(path); mojo::DataPipe pipe; asset_store_->GetAsStream(blink::kSnapshotAssetKey, diff --git a/sky/shell/ui/engine.h b/sky/shell/ui/engine.h index d894571460f..949aa04e3e2 100644 --- a/sky/shell/ui/engine.h +++ b/sky/shell/ui/engine.h @@ -6,6 +6,13 @@ #define SKY_SHELL_UI_ENGINE_H_ #include "flutter/assets/zip_asset_store.h" +#include "flutter/glue/drain_data_pipe_job.h" +#include "flutter/services/engine/sky_engine.mojom.h" +#include "flutter/services/rasterizer/rasterizer.mojom.h" +#include "flutter/sky/engine/public/sky/sky_view_client.h" +#include "flutter/sky/engine/public/sky/sky_view.h" +#include "flutter/sky/shell/rasterizer.h" +#include "flutter/sky/shell/ui_delegate.h" #include "lib/ftl/macros.h" #include "lib/ftl/memory/weak_ptr.h" #include "lib/ftl/tasks/task_runner.h" @@ -16,12 +23,6 @@ #include "mojo/public/cpp/system/handle.h" #include "mojo/public/interfaces/application/service_provider.mojom.h" #include "mojo/services/asset_bundle/interfaces/asset_bundle.mojom.h" -#include "flutter/sky/engine/public/sky/sky_view_client.h" -#include "flutter/sky/engine/public/sky/sky_view.h" -#include "flutter/services/engine/sky_engine.mojom.h" -#include "flutter/services/rasterizer/rasterizer.mojom.h" -#include "flutter/sky/shell/rasterizer.h" -#include "flutter/sky/shell/ui_delegate.h" #include "third_party/skia/include/core/SkPicture.h" namespace sky { @@ -51,7 +52,7 @@ class Engine : public UIDelegate, void RunFromSource(const std::string& main, const std::string& packages, - const std::string& assets_directory); + const std::string& bundle); Dart_Port GetUIIsolateMainPort(); @@ -91,7 +92,6 @@ class Engine : public UIDelegate, void BindToServiceProvider( mojo::InterfaceRequest request); - void RunFromLibrary(const std::string& name); void RunFromSnapshotStream(const std::string& script_uri, mojo::ScopedDataPipeConsumerHandle snapshot); @@ -100,8 +100,9 @@ class Engine : public UIDelegate, void StopAnimator(); void StartAnimatorIfPossible(); - void ConfigureZipAssetBundle(const mojo::String& path); + void ConfigureZipAssetBundle(const std::string& path); void ConfigureDirectoryAssetBundle(const std::string& path); + void ConfigureView(const std::string& script_uri); Config config_; std::unique_ptr animator_; @@ -112,9 +113,10 @@ class Engine : public UIDelegate, mojo::BindingSet service_provider_bindings_; mojo::asset_bundle::AssetBundlePtr root_bundle_; - std::unique_ptr dart_library_provider_; std::unique_ptr sky_view_; + std::unique_ptr snapshot_drainer_; + std::string initial_route_; ViewportMetricsPtr viewport_metrics_; std::string language_code_; diff --git a/snapshotter/main.cc b/snapshotter/main.cc index 89ca0d0bf0d..9ca4a6c7518 100644 --- a/snapshotter/main.cc +++ b/snapshotter/main.cc @@ -116,16 +116,7 @@ tonic::FileLoader& GetLoader() { Dart_Handle HandleLibraryTag(Dart_LibraryTag tag, Dart_Handle library, Dart_Handle url) { - FTL_CHECK(Dart_IsLibrary(library)); - FTL_CHECK(Dart_IsString(url)); - tonic::FileLoader& loader = GetLoader(); - if (tag == Dart_kCanonicalizeUrl) - return loader.CanonicalizeURL(library, url); - if (tag == Dart_kImportTag) - return loader.Import(url); - if (tag == Dart_kSourceTag) - return loader.Source(library, url); - return Dart_NewApiError("Unknown library tag."); + return GetLoader().HandleLibraryTag(tag, library, url); } std::vector CreateSnapshot() { diff --git a/tonic/BUILD.gn b/tonic/BUILD.gn index 8478fc2d2ef..61de7e75390 100644 --- a/tonic/BUILD.gn +++ b/tonic/BUILD.gn @@ -6,31 +6,15 @@ source_set("tonic") { sources = [ "dart_debugger.cc", "dart_debugger.h", - "dart_dependency_catcher.cc", - "dart_dependency_catcher.h", "dart_io.cc", "dart_io.h", - "dart_isolate_reloader.cc", - "dart_isolate_reloader.h", - "dart_library_loader.cc", - "dart_library_loader.h", - "dart_library_provider.cc", - "dart_library_provider.h", - "dart_library_provider_files.cc", - "dart_library_provider_files.h", - "dart_snapshot_loader.cc", - "dart_snapshot_loader.h", "dart_state.cc", "dart_state.h", ] deps = [ - "//base", "//dart/runtime/bin:embedded_dart_io", - "//flutter/glue", - "//lib/tonic/parsers", - "//mojo/data_pipe_utils", - "//mojo/public/cpp/system", + "//lib/ftl", ] public_deps = [ diff --git a/tonic/dart_dependency_catcher.cc b/tonic/dart_dependency_catcher.cc deleted file mode 100644 index f6eec6793fc..00000000000 --- a/tonic/dart_dependency_catcher.cc +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2015 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/tonic/dart_dependency_catcher.h" - -#include "flutter/tonic/dart_library_loader.h" - -namespace blink { - -DartDependencyCatcher::DartDependencyCatcher(DartLibraryLoader& loader) - : loader_(loader) { - loader_.set_dependency_catcher(this); -} - -DartDependencyCatcher::~DartDependencyCatcher() { - loader_.set_dependency_catcher(nullptr); -} - -void DartDependencyCatcher::AddDependency(DartDependency* dependency) { - dependencies_.insert(dependency); -} - -} // namespace blink diff --git a/tonic/dart_dependency_catcher.h b/tonic/dart_dependency_catcher.h deleted file mode 100644 index 740c5e2fd13..00000000000 --- a/tonic/dart_dependency_catcher.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2015 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_TONIC_DART_DEPENDENCY_CATCHER_H_ -#define FLUTTER_TONIC_DART_DEPENDENCY_CATCHER_H_ - -#include - -#include "lib/ftl/macros.h" - -namespace blink { -class DartLibraryLoader; - -// A base class to represent a dependency. -class DartDependency {}; - -// To catch the dependencies for a library, put a DartDependencyCatcher on the -// stack during the call to Dart_LoadLibrary. -class DartDependencyCatcher { - public: - explicit DartDependencyCatcher(DartLibraryLoader& loader); - ~DartDependencyCatcher(); - - void AddDependency(DartDependency* dependency); - const std::unordered_set& dependencies() const { - return dependencies_; - } - - private: - DartLibraryLoader& loader_; - std::unordered_set dependencies_; - - FTL_DISALLOW_COPY_AND_ASSIGN(DartDependencyCatcher); -}; - -} // namespace blink - -#endif // FLUTTER_TONIC_DART_DEPENDENCY_CATCHER_H_ diff --git a/tonic/dart_isolate_reloader.cc b/tonic/dart_isolate_reloader.cc deleted file mode 100644 index d4bddee30b2..00000000000 --- a/tonic/dart_isolate_reloader.cc +++ /dev/null @@ -1,315 +0,0 @@ -// 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. - -#include "flutter/tonic/dart_isolate_reloader.h" - -#include - -#include "flutter/tonic/dart_dependency_catcher.h" -#include "flutter/tonic/dart_library_loader.h" -#include "flutter/tonic/dart_library_provider.h" -#include "flutter/tonic/dart_state.h" -#include "flutter/glue/drain_data_pipe_job.h" -#include "flutter/glue/thread.h" -#include "lib/ftl/logging.h" -#include "lib/ftl/synchronization/monitor.h" -#include "lib/tonic/converter/dart_converter.h" -#include "lib/tonic/logging/dart_error.h" -#include "lib/tonic/scopes/dart_api_scope.h" -#include "lib/tonic/scopes/dart_isolate_scope.h" - -using tonic::ToDart; -using tonic::StdStringToDart; -using tonic::StdStringFromDart; - -namespace blink { - -// As each source file is loaded, a LoadResult is queued to be processed on the -// isolate's thread. A LoadResult contains the payload or an error message. -class DartIsolateReloader::LoadResult { - public: - // Successful load result. - LoadResult(intptr_t tag, - const std::string& url, - const std::string& library_url, - const std::string& resolved_url, - std::vector payload) - : success_(true), - tag_(tag), - url_(url), - library_url_(library_url), - resolved_url_(resolved_url), - payload_(std::move(payload)) { - FTL_DCHECK(success()); - } - - // Error load result. - LoadResult(intptr_t tag, - const std::string& url, - const std::string& library_url, - const std::string& error) - : success_(false), - tag_(tag), - url_(url), - library_url_(library_url), - error_(error) {} - - bool success() const { return success_; } - - Dart_Handle Finish() { - if (!success()) { - return StdStringToDart(error_); - } - Dart_Handle uri = StdStringToDart(url_); - Dart_Handle resolved_uri = Dart_Null(); - if (!resolved_url_.empty()) { - resolved_uri = StdStringToDart(resolved_url_); - } - Dart_Handle library = Dart_Null(); - if (!library_url_.empty()) { - library = Dart_LookupLibrary(StdStringToDart(library_url_)); - } - Dart_Handle source = Dart_NewStringFromUTF8( - reinterpret_cast(payload_.data()), payload_.size()); - Dart_Handle result = Dart_Null(); - switch (tag_) { - case Dart_kImportTag: - result = Dart_LoadLibrary(uri, resolved_uri, source, 0, 0); - break; - case Dart_kSourceTag: - result = Dart_LoadSource(library, uri, resolved_uri, source, 0, 0); - break; - case Dart_kScriptTag: - result = Dart_LoadScript(uri, resolved_uri, source, 0, 0); - break; - } - - if (Dart_IsError(result)) { - return result; - } - return Dart_Null(); - } - - private: - bool success_; - intptr_t tag_; - std::string url_; - std::string library_url_; - std::string resolved_url_; - std::string error_; - std::vector payload_; -}; - -DartIsolateReloader::DartIsolateReloader(DartLibraryProvider* library_provider) - : thread_("DartIsolateReloader"), - library_provider_(library_provider), - load_error_(Dart_Null()), - pending_requests_(0) { - FTL_CHECK(thread_.Start()); -} - -DartIsolateReloader::~DartIsolateReloader() {} - -void DartIsolateReloader::SendRequest(Dart_LibraryTag tag, - Dart_Handle url, - Dart_Handle library_url) { - ftl::RefPtr runner = thread_.task_runner(); - std::string url_string = StdStringFromDart(url); - std::string library_url_string = StdStringFromDart(library_url); - - ftl::MonitorLocker locker(&monitor_); - - // Post a task to the worker thread. This task will request the I/O and - // post a LoadResult to be processed once complete. - runner->PostTask([this, tag, url_string, library_url_string]() { - RequestTask(library_provider_, this, static_cast(tag), url_string, - library_url_string); - }); - - pending_requests_++; -} - -void DartIsolateReloader::PostResult(std::unique_ptr load_result) { - ftl::MonitorLocker locker(&monitor_); - pending_requests_--; - load_results_.push(std::move(load_result)); - locker.Signal(); -} - -// As each source file is requested, a LoadRequest is queued to be processed on -// worker thread. -class DartIsolateReloader::LoadRequest { - public: - LoadRequest(DartLibraryProvider* library_provider, - DartIsolateReloader* isolate_reloader, - intptr_t tag, - const std::string& url, - const std::string& library_url) - : isolate_reloader_(isolate_reloader), - tag_(tag), - url_(url), - library_url_(library_url) { - auto stream = library_provider->GetLibraryAsStream(url_); - OnStreamAvailable(std::move(stream.handle), std::move(stream.resolved_url)); - } - - protected: - void OnStreamAvailable(mojo::ScopedDataPipeConsumerHandle handle, - std::string resolved_url) { - if (!handle.is_valid()) { - std::unique_ptr result( - new DartIsolateReloader::LoadResult( - tag_, url_, library_url_, - "File " + url_ + " could not be read.")); - FTL_LOG(ERROR) << "Load failed for " << url_; - isolate_reloader_->PostResult(std::move(result)); - // We are finished with this request. - delete this; - return; - } - resolved_url_ = std::move(resolved_url); - drainer_.reset(new glue::DrainDataPipeJob( - std::move(handle), [this](std::vector buffer) { - std::unique_ptr result( - new DartIsolateReloader::LoadResult( - tag_, url_, library_url_, resolved_url_, std::move(buffer))); - isolate_reloader_->PostResult(std::move(result)); - // We are finished with this request. - delete this; - })); - } - - private: - DartIsolateReloader* isolate_reloader_; - intptr_t tag_; - std::string url_; - std::string library_url_; - std::string resolved_url_; - std::vector buffer_; - std::unique_ptr drainer_; -}; - -void DartIsolateReloader::RequestTask(DartLibraryProvider* library_provider, - DartIsolateReloader* isolate_reloader, - intptr_t tag, - const std::string& url, - const std::string& library_url) { - FTL_DCHECK(isolate_reloader); - FTL_DCHECK(library_provider); - FTL_DCHECK(tag > 0); - // Construct a new LoadRequest. The pointer is dropped here because - // the request deletes itself on success and failure. - new LoadRequest(library_provider, isolate_reloader, tag, url, library_url); -} - -void DartIsolateReloader::HandleLoadResultLocked(LoadResult* load_result) { - if (load_error_ != Dart_Null()) { - // Already have a sticky error. Just drop this result. - return; - } - - // Drop the lock temporarily around the call to Finish because it may - // trigger a recursive call into the tag handler. - monitor_.Exit(); - Dart_Handle error_or_null = load_result->Finish(); - monitor_.Enter(); - - if (!Dart_IsNull(error_or_null)) { - // Set sticky error. - load_error_ = error_or_null; - } -} - -void DartIsolateReloader::ProcessResultQueueLocked() { - while (load_results_.size() > 0) { - // Grab the first load result. - std::unique_ptr result = std::move(load_results_.front()); - load_results_.pop(); - HandleLoadResultLocked(result.get()); - } -} - -bool DartIsolateReloader::IsCompleteLocked() { - return (pending_requests_ == 0) && load_results_.empty(); -} - -bool DartIsolateReloader::BlockUntilComplete() { - ftl::MonitorLocker locker(&monitor_); - - while (true) { - ProcessResultQueueLocked(); - - if (IsCompleteLocked()) { - break; - } - - // Wait to be notified about new I/O results. - locker.Wait(); - } - return !Dart_IsNull(load_error_); -} - -Dart_Handle DartIsolateReloader::HandleLibraryTag(Dart_LibraryTag tag, - Dart_Handle library, - Dart_Handle url) { - if (tag == Dart_kCanonicalizeUrl) { - // Pass through to actual tag handler. - return DartLibraryLoader::HandleLibraryTag(tag, library, url); - } - DartState* dart_state = DartState::Current(); - FTL_DCHECK(dart_state); - DartIsolateReloader* isolate_reloader = dart_state->isolate_reloader(); - // The first call into the tag handler ends up blocking the calling thread - // until the entire reload has completed. All other calls into the - // tag handler schedule requests and return immediately. - const bool blocking_call = (tag == Dart_kScriptTag); - if (!isolate_reloader) { - // The first call into this tag handler must be for the script. - FTL_DCHECK(tag == Dart_kScriptTag); - // Associate the reloader with the isolate. The reloader is owned - // by the dart_state. - dart_state->set_isolate_reloader( - std::unique_ptr(new DartIsolateReloader( - dart_state->library_loader().library_provider()))); - // Get a pointer to the reloader. - isolate_reloader = dart_state->isolate_reloader(); - // Switch the tag handler. - Dart_SetLibraryTagHandler(DartIsolateReloader::HandleLibraryTag); - } else { - // We should not see another request for the script. - FTL_DCHECK(tag != Dart_kScriptTag); - } - - // Issue I/O request. - isolate_reloader->SendRequest(tag, url, (library != Dart_Null()) - ? Dart_LibraryUrl(library) - : Dart_Null()); - - if (blocking_call) { - // Block and process LoadResults until the load is complete. - const bool load_error = isolate_reloader->BlockUntilComplete(); - // Grab the (possibly null) load error from the reloader before its gone. - Dart_Handle result = isolate_reloader->load_error_; - // The reloader will be deleted once we call set_isolate_reloader below. - isolate_reloader = nullptr; - // Disassociate reloader from the isolate, this causes it to be deleted. - dart_state->set_isolate_reloader(nullptr); - Dart_SetLibraryTagHandler(DartLibraryLoader::HandleLibraryTag); - if (load_error) { - // If we hit an error, return the load error. - return result; - } else { - // Finalize loading. - result = Dart_FinalizeLoading(true); - if (Dart_IsError(result)) { - // If we hit an error, return the load error. - return result; - } - } - } - - return Dart_Null(); -} - -} // namespace blink diff --git a/tonic/dart_isolate_reloader.h b/tonic/dart_isolate_reloader.h deleted file mode 100644 index e546fb99ee7..00000000000 --- a/tonic/dart_isolate_reloader.h +++ /dev/null @@ -1,71 +0,0 @@ -// 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. - -#ifndef FLUTTER_TONIC_DART_ISOLATE_RELOADER_H_ -#define FLUTTER_TONIC_DART_ISOLATE_RELOADER_H_ - -#include -#include -#include - -#include "dart/runtime/include/dart_api.h" -#include "flutter/glue/thread.h" -#include "lib/ftl/macros.h" -#include "lib/ftl/synchronization/monitor.h" - -namespace blink { -class DartLibraryProvider; - -// Reloading an isolate must be an atomic operation, meaning, no other tasks -// can run while reloading. A nested run loop is not sufficient because other -// tasks that invoke Dart code can be run. When |HandleLibraryTag| is invoked -// the calling thread will be blocked until the load has fully completed. To -// avoid relying on the message loop we use our own queue and notification -// mechanism. -class DartIsolateReloader { - public: - // The |DartLibraryProvider| used to load the library sources. - DartIsolateReloader(DartLibraryProvider* library_provider); - ~DartIsolateReloader(); - - static Dart_Handle HandleLibraryTag(Dart_LibraryTag tag, - Dart_Handle library, - Dart_Handle url); - - private: - class LoadRequest; - class LoadResult; - - void SendRequest(Dart_LibraryTag tag, - Dart_Handle url, - Dart_Handle library_url); - - void PostResult(std::unique_ptr load_result); - - static void RequestTask(DartLibraryProvider* library_provider, - DartIsolateReloader* isolate_reloader, - intptr_t tag, - const std::string& url, - const std::string& library_url); - - void HandleLoadResultLocked(LoadResult* load_result); - void ProcessResultQueueLocked(); - bool IsCompleteLocked(); - bool BlockUntilComplete(); - - glue::Thread thread_; - DartLibraryProvider* library_provider_; - - ftl::Monitor monitor_; - // The monitor is used to protect the following fields: - Dart_Handle load_error_; - std::queue> load_results_; - intptr_t pending_requests_; - - FTL_DISALLOW_COPY_AND_ASSIGN(DartIsolateReloader); -}; - -} // namespace blink - -#endif // FLUTTER_TONIC_DART_ISOLATE_RELOADER_H_ diff --git a/tonic/dart_library_loader.cc b/tonic/dart_library_loader.cc deleted file mode 100644 index b4c69ec6e48..00000000000 --- a/tonic/dart_library_loader.cc +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright 2015 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/tonic/dart_library_loader.h" - -#include - -#include "flutter/tonic/dart_dependency_catcher.h" -#include "flutter/tonic/dart_isolate_reloader.h" -#include "flutter/tonic/dart_library_provider.h" -#include "flutter/tonic/dart_state.h" -#include "flutter/glue/drain_data_pipe_job.h" -#include "flutter/glue/trace_event.h" -#include "lib/tonic/converter/dart_converter.h" -#include "lib/tonic/dart_persistent_value.h" -#include "lib/tonic/logging/dart_error.h" -#include "lib/tonic/scopes/dart_api_scope.h" -#include "lib/tonic/scopes/dart_isolate_scope.h" - -using tonic::StdStringFromDart; -using tonic::ToDart; - -namespace blink { - -namespace { - -// Helper to erase a T* from a container of std::unique_ptrs. -template -void EraseUniquePtr(C& container, T* item) { - std::unique_ptr key = std::unique_ptr(item); - container.erase(key); - key.release(); -} - -} // namespace - -// A DartLibraryLoader::Job represents a network load. It fetches data from the -// network and buffers the data in std::vector. To cancel the job, delete this -// object. -class DartLibraryLoader::Job : public DartDependency { - public: - Job(DartLibraryLoader* loader, const std::string& name) - : loader_(loader), name_(name) { - auto stream = loader->library_provider()->GetLibraryAsStream(name); - OnStreamAvailable(std::move(stream.handle), std::move(stream.resolved_url)); - } - - const std::string& name() const { return name_; } - const std::string& resolved_url() const { return resolved_url_; } - - protected: - DartLibraryLoader* loader_; - - virtual void OnDataAvailable(std::vector buffer) = 0; - - private: - void OnStreamAvailable(mojo::ScopedDataPipeConsumerHandle pipe, - const std::string& resolved_url) { - if (!pipe.is_valid()) { - loader_->DidFailJob(this); - return; - } - resolved_url_ = resolved_url; - drainer_.reset(new glue::DrainDataPipeJob( - std::move(pipe), [this](std::vector buffer) { - OnDataAvailable(std::move(buffer)); - })); - } - - std::string name_; - std::string resolved_url_; - std::unique_ptr drainer_; -}; - -class DartLibraryLoader::ImportJob : public Job { - public: - ImportJob(DartLibraryLoader* loader, - const std::string& name, - bool should_load_as_script) - : Job(loader, name), should_load_as_script_(should_load_as_script) { - TRACE_EVENT_ASYNC_BEGIN1("flutter", "DartLibraryLoader::ImportJob", this, - "url", name); - } - - bool should_load_as_script() const { return should_load_as_script_; } - - private: - void OnDataAvailable(std::vector buffer) override { - TRACE_EVENT_ASYNC_END0("flutter", "DartLibraryLoader::ImportJob", this); - loader_->DidCompleteImportJob(this, std::move(buffer)); - } - - bool should_load_as_script_; -}; - -class DartLibraryLoader::SourceJob : public Job { - public: - SourceJob(DartLibraryLoader* loader, - const std::string& name, - Dart_Handle library) - : Job(loader, name), library_(loader->dart_state(), library) { - TRACE_EVENT_ASYNC_BEGIN1("flutter", "DartLibraryLoader::SourceJob", this, - "url", name); - } - - Dart_PersistentHandle library() const { return library_.value(); } - - private: - void OnDataAvailable(std::vector buffer) override { - TRACE_EVENT_ASYNC_END0("flutter", "DartLibraryLoader::SourceJob", this); - loader_->DidCompleteSourceJob(this, std::move(buffer)); - } - - tonic::DartPersistentValue library_; -}; - -// A DependencyWatcher represents a request to watch for when a given set of -// dependencies (either libraries or parts of libraries) have finished loading. -// When the dependencies are satisfied (including transitive dependencies), then -// the |callback| will be invoked. -class DartLibraryLoader::DependencyWatcher { - public: - DependencyWatcher(const std::unordered_set& dependencies, - const ftl::Closure& callback) - : dependencies_(dependencies), callback_(callback) { - FTL_DCHECK(!dependencies_.empty()); - } - - bool DidResolveDependency( - DartDependency* resolved_dependency, - const std::unordered_set& new_dependencies) { - const auto& it = dependencies_.find(resolved_dependency); - if (it == dependencies_.end()) - return false; - dependencies_.erase(it); - for (const auto& dependency : new_dependencies) - dependencies_.insert(dependency); - return dependencies_.empty(); - } - - const ftl::Closure& callback() const { return callback_; } - - private: - std::unordered_set dependencies_; - ftl::Closure callback_; -}; - -// A WatcherSignaler is responsible for signaling DependencyWatchers when their -// dependencies resolve and for calling the DependencyWatcher's callback. We use -// a separate object of this task because we want to carefully manage when we -// call the callbacks, which can call into us again reentrantly. -// -// WatcherSignaler is designed to be placed on the stack as a RAII. After its -// destructor runs, we might have executed aribitrary script. -class DartLibraryLoader::WatcherSignaler { - public: - WatcherSignaler(DartLibraryLoader& loader, - DartDependency* resolved_dependency) - : loader_(loader), - catcher_(new DartDependencyCatcher(loader)), - resolved_dependency_(resolved_dependency) {} - - ~WatcherSignaler() { - std::vector completed_watchers; - for (const auto& watcher : loader_.dependency_watchers_) { - if (watcher->DidResolveDependency(resolved_dependency_, - catcher_->dependencies())) - completed_watchers.push_back(watcher.get()); - } - - // Notice that we remove the dependency catcher and extract all the - // callbacks before running any of them. We don't want to be re-entered - // below the callbacks and end up in an inconsistent state. - catcher_ = nullptr; - std::vector callbacks; - for (const auto& watcher : completed_watchers) { - callbacks.push_back(watcher->callback()); - EraseUniquePtr(loader_.dependency_watchers_, watcher); - } - - // Finally, run all the callbacks while touching only data on the stack. - for (const auto& callback : callbacks) - callback(); - } - - private: - DartLibraryLoader& loader_; - std::unique_ptr catcher_; - DartDependency* resolved_dependency_; -}; - -DartLibraryLoader::DartLibraryLoader(DartState* dart_state) - : dart_state_(dart_state), - library_provider_(nullptr), - dependency_catcher_(nullptr) {} - -DartLibraryLoader::~DartLibraryLoader() {} - -Dart_Handle DartLibraryLoader::HandleLibraryTag(Dart_LibraryTag tag, - Dart_Handle library, - Dart_Handle url) { - FTL_DCHECK(Dart_IsLibrary(library) || Dart_IsNull(library)); - FTL_DCHECK(Dart_IsString(url)); - if (tag == Dart_kCanonicalizeUrl) { - return DartState::Current()->library_loader().CanonicalizeURL(library, url); - } - if (tag == Dart_kImportTag) { - return DartState::Current()->library_loader().Import(library, url); - } - if (tag == Dart_kSourceTag) { - return DartState::Current()->library_loader().Source(library, url); - } - if (tag == Dart_kScriptTag) { - return DartIsolateReloader::HandleLibraryTag(tag, library, url); - } - FTL_NOTREACHED(); - return Dart_NewApiError("Unknown library tag."); -} - -void DartLibraryLoader::WaitForDependencies( - const std::unordered_set& dependencies, - const ftl::Closure& callback) { - if (dependencies.empty()) - return callback(); - dependency_watchers_.insert(std::unique_ptr( - new DependencyWatcher(dependencies, callback))); -} - -void DartLibraryLoader::LoadLibrary(const std::string& name) { - const auto& result = pending_libraries_.insert(std::make_pair(name, nullptr)); - if (result.second) { - // New entry. - std::unique_ptr job = - std::unique_ptr(new ImportJob(this, name, false)); - result.first->second = job.get(); - jobs_.insert(std::move(job)); - } - if (dependency_catcher_) - dependency_catcher_->AddDependency(result.first->second); -} - -void DartLibraryLoader::LoadScript(const std::string& name) { - const auto& result = pending_libraries_.insert(std::make_pair(name, nullptr)); - if (result.second) { - // New entry. - std::unique_ptr job = - std::unique_ptr(new ImportJob(this, name, true)); - result.first->second = job.get(); - jobs_.insert(std::move(job)); - } - if (dependency_catcher_) - dependency_catcher_->AddDependency(result.first->second); -} - -Dart_Handle DartLibraryLoader::Import(Dart_Handle library, Dart_Handle url) { - LoadLibrary(StdStringFromDart(url)); - return Dart_True(); -} - -Dart_Handle DartLibraryLoader::Source(Dart_Handle library, Dart_Handle url) { - std::unique_ptr job = std::unique_ptr( - new SourceJob(this, StdStringFromDart(url), library)); - if (dependency_catcher_) - dependency_catcher_->AddDependency(job.get()); - jobs_.insert(std::move(job)); - return Dart_True(); -} - -Dart_Handle DartLibraryLoader::CanonicalizeURL(Dart_Handle library, - Dart_Handle url) { - return library_provider_->CanonicalizeURL(library, url); -} - -void DartLibraryLoader::DidCompleteImportJob(ImportJob* job, - std::vector buffer) { - tonic::DartIsolateScope scope(dart_state_->isolate()); - tonic::DartApiScope api_scope; - - WatcherSignaler watcher_signaler(*this, job); - - Dart_Handle result; - Dart_Handle source = Dart_NewStringFromUTF8( - reinterpret_cast(buffer.data()), buffer.size()); - - if (job->should_load_as_script()) { - result = Dart_LoadScript(ToDart(job->name()), ToDart(job->resolved_url()), - source, 0, 0); - } else { - result = Dart_LoadLibrary(ToDart(job->name()), ToDart(job->resolved_url()), - source, 0, 0); - } - if (Dart_IsError(result)) { - FTL_LOG(ERROR) << "Error Loading " << job->name() << " " - << Dart_GetError(result); - } - - pending_libraries_.erase(job->name()); - EraseUniquePtr(jobs_, job); -} - -void DartLibraryLoader::DidCompleteSourceJob(SourceJob* job, - std::vector buffer) { - tonic::DartIsolateScope scope(dart_state_->isolate()); - tonic::DartApiScope api_scope; - - WatcherSignaler watcher_signaler(*this, job); - - Dart_Handle source = Dart_NewStringFromUTF8( - reinterpret_cast(buffer.data()), buffer.size()); - Dart_Handle result = Dart_LoadSource( - Dart_HandleFromPersistent(job->library()), ToDart(job->name()), - ToDart(job->resolved_url()), source, 0, 0); - - if (Dart_IsError(result)) { - FTL_LOG(ERROR) << "Error Loading " << job->name() << " " - << Dart_GetError(result); - } - - EraseUniquePtr(jobs_, job); -} - -void DartLibraryLoader::DidFailJob(Job* job) { - tonic::DartIsolateScope scope(dart_state_->isolate()); - tonic::DartApiScope api_scope; - - WatcherSignaler watcher_signaler(*this, job); - - FTL_LOG(ERROR) << "Library Load failed: " << job->name(); - // TODO(eseidel): Call Dart_LibraryHandleError in the SourceJob case? - - EraseUniquePtr(jobs_, job); -} - -} // namespace blink diff --git a/tonic/dart_library_loader.h b/tonic/dart_library_loader.h deleted file mode 100644 index 346da4b57f0..00000000000 --- a/tonic/dart_library_loader.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2015 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_TONIC_DART_LIBRARY_LOADER_H_ -#define FLUTTER_TONIC_DART_LIBRARY_LOADER_H_ - -#include -#include -#include -#include -#include - -#include "dart/runtime/include/dart_api.h" -#include "lib/ftl/functional/closure.h" -#include "lib/ftl/logging.h" -#include "lib/ftl/macros.h" - -namespace blink { -class DartDependency; -class DartDependencyCatcher; -class DartLibraryProvider; -class DartState; - -// TODO(abarth): This class seems more complicated than it needs to be. Is -// there some way of simplifying this system? For example, we have a bunch -// of inner classes that could potentially be factored out in some other way. -class DartLibraryLoader { - public: - explicit DartLibraryLoader(DartState* dart_state); - ~DartLibraryLoader(); - - // TODO(dart): This can be called both on the main thread from application - // isolates or from the handle watcher isolate thread. - static Dart_Handle HandleLibraryTag(Dart_LibraryTag tag, - Dart_Handle library, - Dart_Handle url); - - void LoadLibrary(const std::string& name); - void LoadScript(const std::string& name); - - void WaitForDependencies( - const std::unordered_set& dependencies, - const ftl::Closure& callback); - - void set_dependency_catcher(DartDependencyCatcher* dependency_catcher) { - FTL_DCHECK(!dependency_catcher_ || !dependency_catcher); - dependency_catcher_ = dependency_catcher; - } - - DartState* dart_state() const { return dart_state_; } - - DartLibraryProvider* library_provider() const { return library_provider_; } - - // The |DartLibraryProvider| must outlive the |DartLibraryLoader|. - void set_library_provider(DartLibraryProvider* library_provider) { - library_provider_ = library_provider; - } - - private: - class Job; - class ImportJob; - class SourceJob; - class DependencyWatcher; - class WatcherSignaler; - - Dart_Handle Import(Dart_Handle library, Dart_Handle url); - Dart_Handle Source(Dart_Handle library, Dart_Handle url); - Dart_Handle CanonicalizeURL(Dart_Handle library, Dart_Handle url); - void DidCompleteImportJob(ImportJob* job, std::vector buffer); - void DidCompleteSourceJob(SourceJob* job, std::vector buffer); - void DidFailJob(Job* job); - - DartState* dart_state_; - DartLibraryProvider* library_provider_; - std::unordered_map pending_libraries_; - std::unordered_set> jobs_; - std::unordered_set> dependency_watchers_; - DartDependencyCatcher* dependency_catcher_; - - FTL_DISALLOW_COPY_AND_ASSIGN(DartLibraryLoader); -}; - -} // namespace blink - -#endif // FLUTTER_TONIC_DART_LIBRARY_LOADER_H_ diff --git a/tonic/dart_library_provider.cc b/tonic/dart_library_provider.cc deleted file mode 100644 index 3495170dd82..00000000000 --- a/tonic/dart_library_provider.cc +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2015 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/tonic/dart_library_provider.h" - -namespace blink { - -DartLibraryProvider::~DartLibraryProvider() { -} - -} // namespace blink diff --git a/tonic/dart_library_provider.h b/tonic/dart_library_provider.h deleted file mode 100644 index 57b397bdec4..00000000000 --- a/tonic/dart_library_provider.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2015 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_TONIC_DART_LIBRARY_PROVIDER_H_ -#define FLUTTER_TONIC_DART_LIBRARY_PROVIDER_H_ - -#include -#include - -#include "dart/runtime/include/dart_api.h" -#include "mojo/public/cpp/system/data_pipe.h" - -namespace blink { - -struct DartLibraryStream { - mojo::ScopedDataPipeConsumerHandle handle; - std::string resolved_url; -}; - -class DartLibraryProvider { - public: - virtual DartLibraryStream GetLibraryAsStream(const std::string& name) = 0; - - virtual Dart_Handle CanonicalizeURL(Dart_Handle library, Dart_Handle url) = 0; - - virtual ~DartLibraryProvider(); -}; - -} // namespace blink - -#endif // FLUTTER_TONIC_DART_LIBRARY_PROVIDER_H_ diff --git a/tonic/dart_library_provider_files.cc b/tonic/dart_library_provider_files.cc deleted file mode 100644 index a8cd455b971..00000000000 --- a/tonic/dart_library_provider_files.cc +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2015 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/tonic/dart_library_provider_files.h" - -#include "base/bind.h" -#include "base/files/file_util.h" -#include "base/strings/string_util.h" -#include "base/threading/worker_pool.h" -#include "lib/tonic/converter/dart_converter.h" -#include "mojo/data_pipe_utils/data_pipe_utils.h" - -namespace sky { -namespace shell { -namespace { - -void CopyComplete(base::FilePath file, std::string uri, bool success) { - if (!success) - LOG(FATAL) << "Failed to load " << file.AsUTF8Unsafe() << " (" << uri - << ")"; -} - -// Extract the scheme prefix ('package:' or 'file:' from ) -static std::string ExtractSchemePrefix(std::string url) { - if (base::StartsWithASCII(url, "package:", true)) { - return "package:"; - } else if (base::StartsWithASCII(url, "file:", true)) { - return "file:"; - } - return ""; -} - -// Extract the path from a package: or file: url. -static std::string ExtractPath(std::string url) { - if (base::StartsWithASCII(url, "package:", true)) { - base::ReplaceFirstSubstringAfterOffset(&url, 0, "package:", ""); - } else if (base::StartsWithASCII(url, "file:", true)) { - base::ReplaceFirstSubstringAfterOffset(&url, 0, "file:", ""); - } - return url; -} - -base::FilePath SimplifyPath(const base::FilePath& path) { - std::vector components; - path.GetComponents(&components); - auto it = components.begin(); - base::FilePath result(*it++); - for (; it != components.end(); it++) { - auto& component = *it; - if (component == base::FilePath::kCurrentDirectory) - continue; - if (component == base::FilePath::kParentDirectory) - result = result.DirName(); - else - result = result.Append(component); - } - return result; -} - -} // namespace - -DartLibraryProviderFiles::DartLibraryProviderFiles() {} - -DartLibraryProviderFiles::~DartLibraryProviderFiles() {} - -void DartLibraryProviderFiles::LoadPackagesMap(const std::string& packages) { - packages_ = base::FilePath(packages); - std::string packages_source; - if (!base::ReadFileToString(base::MakeAbsoluteFilePath(packages_), - &packages_source)) { - LOG(ERROR) << "error: Unable to load .packages file '" - << packages_.AsUTF8Unsafe() << "'."; - exit(1); - } - std::string error; - if (!packages_map_.Parse(packages_source, &error)) { - LOG(ERROR) << "error: Unable to parse .packages file '" - << packages_.AsUTF8Unsafe() << "'.\n" - << error; - exit(1); - } -} - -blink::DartLibraryStream DartLibraryProviderFiles::GetLibraryAsStream( - const std::string& name) { - mojo::DataPipe pipe; - base::FilePath path = GetFilePathForURL(name); - base::FilePath source = base::MakeAbsoluteFilePath(path); - blink::DartLibraryStream result; - result.handle = std::move(pipe.consumer_handle); - result.resolved_url = "file://" + source.value(); - scoped_refptr runner = - base::WorkerPool::GetTaskRunner(true); - mojo::common::CopyFromFile(source, pipe.producer_handle.Pass(), 0, - runner.get(), - base::Bind(&CopyComplete, source, name)); - return result; -} - -Dart_Handle DartLibraryProviderFiles::CanonicalizeURL(Dart_Handle library, - Dart_Handle url) { - std::string string = tonic::StdStringFromDart(url); - if (base::StartsWithASCII(string, "dart:", true)) - return url; - if (base::StartsWithASCII(string, "package:", true)) - return url; - if (base::StartsWithASCII(string, "file:", true)) { - base::ReplaceFirstSubstringAfterOffset(&string, 0, "file:", ""); - return tonic::StdStringToDart(string); - ; - } - - std::string library_url = tonic::StdStringFromDart(Dart_LibraryUrl(library)); - std::string prefix = ExtractSchemePrefix(library_url); - std::string path = ExtractPath(library_url); - base::FilePath base_path(path); - base::FilePath resolved_path = base_path.DirName().Append(string); - base::FilePath normalized_path = SimplifyPath(resolved_path); - return tonic::StdStringToDart(prefix + normalized_path.AsUTF8Unsafe()); -} - -base::FilePath DartLibraryProviderFiles::GetFilePathForURL(std::string url) { - if (base::StartsWithASCII(url, "package:", true)) - return GetFilePathForPackageURL(url); - if (base::StartsWithASCII(url, "file:", true)) - return GetFilePathForFileURL(url); - - return base::FilePath(url); -} - -base::FilePath DartLibraryProviderFiles::GetFilePathForPackageURL( - std::string url) { - DCHECK(base::StartsWithASCII(url, "package:", true)); - base::ReplaceFirstSubstringAfterOffset(&url, 0, "package:", ""); - size_t slash = url.find('/'); - if (slash == std::string::npos) - return base::FilePath(); - std::string package = url.substr(0, slash); - std::string library_path = url.substr(slash + 1); - std::string package_path = packages_map_.Resolve(package); - if (package_path.empty()) - return base::FilePath(); - if (base::StartsWithASCII(package_path, "file://", true)) { - base::ReplaceFirstSubstringAfterOffset(&package_path, 0, "file://", ""); - return base::FilePath(package_path + library_path); - } - return packages_.DirName().Append(package_path).Append(library_path); -} - -base::FilePath DartLibraryProviderFiles::GetFilePathForFileURL( - std::string url) { - DCHECK(base::StartsWithASCII(url, "file://", true)); - base::ReplaceFirstSubstringAfterOffset(&url, 0, "file://", ""); - return base::FilePath(url); -} - -} // namespace shell -} // namespace sky diff --git a/tonic/dart_library_provider_files.h b/tonic/dart_library_provider_files.h deleted file mode 100644 index 7746c5b60c2..00000000000 --- a/tonic/dart_library_provider_files.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2015 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 SKY_SHELL_DART_DART_LIBRARY_PROVIDER_FILES_H_ -#define SKY_SHELL_DART_DART_LIBRARY_PROVIDER_FILES_H_ - -#include "base/files/file_path.h" -#include "flutter/tonic/dart_library_provider.h" -#include "lib/ftl/macros.h" -#include "lib/tonic/parsers/packages_map.h" - -namespace sky { -namespace shell { - -class DartLibraryProviderFiles : public blink::DartLibraryProvider { - public: - DartLibraryProviderFiles(); - ~DartLibraryProviderFiles() override; - - void LoadPackagesMap(const std::string& packages); - - protected: - // |DartLibraryProvider| implementation: - blink::DartLibraryStream GetLibraryAsStream(const std::string& name) override; - Dart_Handle CanonicalizeURL(Dart_Handle library, Dart_Handle url) override; - - private: - base::FilePath GetFilePathForURL(std::string url); - base::FilePath GetFilePathForPackageURL(std::string url); - base::FilePath GetFilePathForFileURL(std::string url); - - base::FilePath packages_; - tonic::PackagesMap packages_map_; - - FTL_DISALLOW_COPY_AND_ASSIGN(DartLibraryProviderFiles); -}; - -} // namespace shell -} // namespace sky - -#endif // SKY_SHELL_DART_DART_LIBRARY_PROVIDER_FILES_H_ diff --git a/tonic/dart_snapshot_loader.cc b/tonic/dart_snapshot_loader.cc deleted file mode 100644 index c6546df4d13..00000000000 --- a/tonic/dart_snapshot_loader.cc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2015 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/tonic/dart_snapshot_loader.h" - -#include - -#include "flutter/tonic/dart_state.h" -#include "flutter/glue/trace_event.h" -#include "lib/tonic/converter/dart_converter.h" -#include "lib/tonic/logging/dart_error.h" -#include "lib/tonic/scopes/dart_api_scope.h" -#include "lib/tonic/scopes/dart_isolate_scope.h" - -using tonic::LogIfError; - -namespace blink { - -DartSnapshotLoader::DartSnapshotLoader(tonic::DartState* dart_state) - : dart_state_(dart_state->GetWeakPtr()) {} - -DartSnapshotLoader::~DartSnapshotLoader() {} - -void DartSnapshotLoader::LoadSnapshot(mojo::ScopedDataPipeConsumerHandle pipe, - const ftl::Closure& callback) { - TRACE_EVENT_ASYNC_BEGIN0("flutter", "DartSnapshotLoader::LoadSnapshot", this); - - drainer_.reset(new glue::DrainDataPipeJob( - std::move(pipe), [this, callback](std::vector buffer) { - TRACE_EVENT_ASYNC_END0("flutter", "DartSnapshotLoader::LoadSnapshot", - this); - // TODO(abarth): Should we check dart_state_ for null? - { - tonic::DartIsolateScope scope(dart_state_->isolate()); - tonic::DartApiScope api_scope; - - LogIfError(Dart_LoadScriptFromSnapshot( - reinterpret_cast(buffer.data()), buffer.size())); - } - - callback(); - })); -} - -} // namespace blink diff --git a/tonic/dart_snapshot_loader.h b/tonic/dart_snapshot_loader.h deleted file mode 100644 index 237186c3f10..00000000000 --- a/tonic/dart_snapshot_loader.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2015 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_TONIC_DART_SNAPSHOT_LOADER_H_ -#define FLUTTER_TONIC_DART_SNAPSHOT_LOADER_H_ - -#include - -#include "dart/runtime/include/dart_api.h" -#include "flutter/glue/drain_data_pipe_job.h" -#include "lib/ftl/functional/closure.h" -#include "lib/ftl/macros.h" -#include "lib/tonic/dart_state.h" - -namespace blink { - -class DartSnapshotLoader { - public: - explicit DartSnapshotLoader(tonic::DartState* dart_state); - ~DartSnapshotLoader(); - - void LoadSnapshot(mojo::ScopedDataPipeConsumerHandle pipe, - const ftl::Closure& callback); - - private: - ftl::WeakPtr dart_state_; - std::unique_ptr drainer_; - - FTL_DISALLOW_COPY_AND_ASSIGN(DartSnapshotLoader); -}; - -} // namespace blink - -#endif // FLUTTER_TONIC_DART_SNAPSHOT_LOADER_H_ diff --git a/tonic/dart_state.cc b/tonic/dart_state.cc index c0a85d5a514..08a12698627 100644 --- a/tonic/dart_state.cc +++ b/tonic/dart_state.cc @@ -4,13 +4,9 @@ #include "flutter/tonic/dart_state.h" -#include "lib/tonic/converter/dart_converter.h" -#include "flutter/tonic/dart_library_loader.h" - namespace blink { -DartState::DartState() - : library_loader_(new DartLibraryLoader(this)) {} +DartState::DartState() {} DartState::~DartState() {} diff --git a/tonic/dart_state.h b/tonic/dart_state.h index 37724a0de20..c393e4e1125 100644 --- a/tonic/dart_state.h +++ b/tonic/dart_state.h @@ -6,21 +6,13 @@ #define FLUTTER_TONIC_DART_STATE_H_ #include "dart/runtime/include/dart_api.h" -#include "flutter/tonic/dart_isolate_reloader.h" #include "lib/tonic/dart_persistent_value.h" #include "lib/tonic/dart_state.h" #include "lib/tonic/scopes/dart_api_scope.h" #include "lib/tonic/scopes/dart_isolate_scope.h" namespace blink { -class DartExceptionFactory; -class DartLibraryLoader; -// DartState represents the state associated with a given Dart isolate. The -// lifetime of this object is controlled by the DartVM. If you want to hold a -// reference to a DartState instance, please hold a base::WeakPtr. -// -// DartState is analogous to gin::PerIsolateData and JSC::ExecState. class DartState : public tonic::DartState { public: DartState(); @@ -29,19 +21,6 @@ class DartState : public tonic::DartState { static DartState* From(Dart_Isolate isolate); static DartState* Current(); - DartLibraryLoader& library_loader() { return *library_loader_; } - - // Takes ownership of |isolate_reloader|. - void set_isolate_reloader( - std::unique_ptr isolate_reloader) { - isolate_reloader_ = std::move(isolate_reloader); - } - DartIsolateReloader* isolate_reloader() { return isolate_reloader_.get(); } - - private: - std::unique_ptr library_loader_; - std::unique_ptr isolate_reloader_; - protected: FTL_DISALLOW_COPY_AND_ASSIGN(DartState); };