mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Group together externally-managed UIDartState. It's a frequent pattern to enable access to shell resources from the framework via UIDartState. These handles are passed through several other objects, where they lay mostly dormant. This refactor just aims to ease maintenance of this state. UIDartState is essentially just an easy to extend bus for dropping off the shell kids in UIDartState, with constructors/operators that remove the need for providing a full initializer lists in unittests.
175 lines
5.3 KiB
C++
175 lines
5.3 KiB
C++
// 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 "flutter/testing/dart_isolate_runner.h"
|
|
|
|
#include "flutter/runtime/isolate_configuration.h"
|
|
|
|
namespace flutter {
|
|
namespace testing {
|
|
AutoIsolateShutdown::AutoIsolateShutdown(std::shared_ptr<DartIsolate> isolate,
|
|
fml::RefPtr<fml::TaskRunner> runner)
|
|
: isolate_(std::move(isolate)), runner_(std::move(runner)) {}
|
|
|
|
AutoIsolateShutdown::~AutoIsolateShutdown() {
|
|
if (!isolate_->IsShuttingDown()) {
|
|
Shutdown();
|
|
}
|
|
fml::AutoResetWaitableEvent latch;
|
|
fml::TaskRunner::RunNowOrPostTask(runner_, [this, &latch]() {
|
|
// Delete isolate on thread.
|
|
isolate_.reset();
|
|
latch.Signal();
|
|
});
|
|
latch.Wait();
|
|
}
|
|
|
|
void AutoIsolateShutdown::Shutdown() {
|
|
if (!IsValid()) {
|
|
return;
|
|
}
|
|
fml::AutoResetWaitableEvent latch;
|
|
fml::TaskRunner::RunNowOrPostTask(
|
|
runner_, [isolate = isolate_.get(), &latch]() {
|
|
if (!isolate->Shutdown()) {
|
|
FML_LOG(ERROR) << "Could not shutdown isolate.";
|
|
FML_CHECK(false);
|
|
}
|
|
latch.Signal();
|
|
});
|
|
latch.Wait();
|
|
}
|
|
|
|
[[nodiscard]] bool AutoIsolateShutdown::RunInIsolateScope(
|
|
std::function<bool(void)> closure) {
|
|
if (!IsValid()) {
|
|
return false;
|
|
}
|
|
|
|
bool result = false;
|
|
fml::AutoResetWaitableEvent latch;
|
|
fml::TaskRunner::RunNowOrPostTask(
|
|
runner_, [this, &result, &latch, closure]() {
|
|
tonic::DartIsolateScope scope(isolate_->isolate());
|
|
tonic::DartApiScope api_scope;
|
|
if (closure) {
|
|
result = closure();
|
|
}
|
|
latch.Signal();
|
|
});
|
|
latch.Wait();
|
|
return true;
|
|
}
|
|
|
|
std::unique_ptr<AutoIsolateShutdown> RunDartCodeInIsolateOnUITaskRunner(
|
|
DartVMRef& vm_ref,
|
|
const Settings& p_settings,
|
|
const TaskRunners& task_runners,
|
|
std::string entrypoint,
|
|
const std::vector<std::string>& args,
|
|
const std::string& kernel_file_path,
|
|
fml::WeakPtr<IOManager> io_manager,
|
|
std::shared_ptr<VolatilePathTracker> volatile_path_tracker) {
|
|
FML_CHECK(task_runners.GetUITaskRunner()->RunsTasksOnCurrentThread());
|
|
|
|
if (!vm_ref) {
|
|
return nullptr;
|
|
}
|
|
|
|
auto vm_data = vm_ref.GetVMData();
|
|
|
|
if (!vm_data) {
|
|
return nullptr;
|
|
}
|
|
|
|
auto settings = p_settings;
|
|
|
|
settings.dart_entrypoint_args = args;
|
|
|
|
if (!DartVM::IsRunningPrecompiledCode()) {
|
|
if (!fml::IsFile(kernel_file_path)) {
|
|
FML_LOG(ERROR) << "Could not locate kernel file.";
|
|
return nullptr;
|
|
}
|
|
|
|
auto kernel_file = fml::OpenFile(kernel_file_path.c_str(), false,
|
|
fml::FilePermission::kRead);
|
|
|
|
if (!kernel_file.is_valid()) {
|
|
FML_LOG(ERROR) << "Kernel file descriptor was invalid.";
|
|
return nullptr;
|
|
}
|
|
|
|
auto kernel_mapping = std::make_unique<fml::FileMapping>(kernel_file);
|
|
|
|
if (kernel_mapping->GetMapping() == nullptr) {
|
|
FML_LOG(ERROR) << "Could not set up kernel mapping.";
|
|
return nullptr;
|
|
}
|
|
|
|
settings.application_kernels = fml::MakeCopyable(
|
|
[kernel_mapping = std::move(kernel_mapping)]() mutable -> Mappings {
|
|
Mappings mappings;
|
|
mappings.emplace_back(std::move(kernel_mapping));
|
|
return mappings;
|
|
});
|
|
}
|
|
|
|
auto isolate_configuration =
|
|
IsolateConfiguration::InferFromSettings(settings);
|
|
|
|
UIDartState::Context context(std::move(task_runners));
|
|
context.io_manager = io_manager;
|
|
context.advisory_script_uri = "main.dart";
|
|
context.advisory_script_entrypoint = entrypoint.c_str();
|
|
|
|
auto isolate =
|
|
DartIsolate::CreateRunningRootIsolate(
|
|
settings, // settings
|
|
vm_data->GetIsolateSnapshot(), // isolate snapshot
|
|
nullptr, // platform configuration
|
|
DartIsolate::Flags{}, // flags
|
|
settings.isolate_create_callback, // isolate create callback
|
|
settings.isolate_shutdown_callback, // isolate shutdown callback
|
|
entrypoint, // entrypoint
|
|
std::nullopt, // library
|
|
std::move(isolate_configuration), // isolate configuration
|
|
context // engine context
|
|
)
|
|
.lock();
|
|
|
|
if (!isolate) {
|
|
FML_LOG(ERROR) << "Could not create running isolate.";
|
|
return nullptr;
|
|
}
|
|
|
|
return std::make_unique<AutoIsolateShutdown>(isolate,
|
|
task_runners.GetUITaskRunner());
|
|
}
|
|
|
|
std::unique_ptr<AutoIsolateShutdown> RunDartCodeInIsolate(
|
|
DartVMRef& vm_ref,
|
|
const Settings& settings,
|
|
const TaskRunners& task_runners,
|
|
std::string entrypoint,
|
|
const std::vector<std::string>& args,
|
|
const std::string& kernel_file_path,
|
|
fml::WeakPtr<IOManager> io_manager,
|
|
std::shared_ptr<VolatilePathTracker> volatile_path_tracker) {
|
|
std::unique_ptr<AutoIsolateShutdown> result;
|
|
fml::AutoResetWaitableEvent latch;
|
|
fml::TaskRunner::RunNowOrPostTask(
|
|
task_runners.GetUITaskRunner(), fml::MakeCopyable([&]() mutable {
|
|
result = RunDartCodeInIsolateOnUITaskRunner(
|
|
vm_ref, settings, task_runners, entrypoint, args, kernel_file_path,
|
|
io_manager, std::move(volatile_path_tracker));
|
|
latch.Signal();
|
|
}));
|
|
latch.Wait();
|
|
return result;
|
|
}
|
|
|
|
} // namespace testing
|
|
} // namespace flutter
|